自定義組件 *
- Android怎么動態(tài)引用組件?
動態(tài)引用:主程序和組件是分離的,組件可以單獨升級和卸載。
靜態(tài)引用:將組件和主程序一起封裝在編譯后的目標文件中。
可以動態(tài)引用的組件有:未安裝的apk文件、包括class.dex文件的jar文件、JavaScript腳本、四大應用程序組件(Activity,Service,BroadcastReceiver,Content Provider)。 - 如何將可視組件封裝在jar文件中以及如何通過java代碼適應不同的屏幕分辨率?
jar文件可以封裝很多類型的組件,如可視組件(對Android SDK原生組件的擴展),Activity,Service,BroadcastReceiver,ContentProvider等。
封裝:直接將可視組件的.class文件放到jar文件中即可,組件使用的資源文件要放到主工程的res目錄的相關(guān)子目錄中。在XML布局文件中使用組件要指定全名(包名+類名)。
在自定義可視化組件時需要考慮屏幕分辨率的問題,需要將與屏幕分辨率無關(guān)的dp或sp轉(zhuǎn)換成實際的像素點:
DisplayMetrics displayMetrics = new DisplayMetrics();
displayMetrics.setToDefaults();
int pixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dip, displayMetrics); - 怎么編寫一個自定義可視組件?
開發(fā)模式:
1.擴展現(xiàn)有的組件。
2.組合多種組件。
3.可以從View繼承。 - Android支持的四大應用程序組件可以封裝在jar文件中嗎?使用時該注意什么?
可以,并在Android工程中靜態(tài)引用jar文件。使用時需要在AndroidManifest.xml文件中注冊。 - 如何動態(tài)裝載apk文件(未安裝)的類?
//my.apk表示要動態(tài)加載的apk文件,my_temp.apk表示為了優(yōu)化臨時生產(chǎn)的apk文件
DexFile dexFile = dalvik.system.DexFile.loadDex(
"/sdcard/my.apk", "/sdcard/my_temp.apk", 0);
//裝載apk文件中的類并創(chuàng)建該類的對象實例
Object obj = dexFile.loadClass(
"mobile.android.file.explorer.widget.Test", null).newInstance();
//利用反射技術(shù)獲取getName方法的Method對象
Method method = obj.getClass().getDeclaredMethod("getName", null);
//調(diào)用類中的方法,并獲取方法返回值
String result = String.valueOf(method.invoke(obj, null));
【拓展】強類型與aidl文件
如果使用強類型訪問apk文件中的類,一般需要將該類實現(xiàn)的接口提供給調(diào)用者,或者提供一個aidl文件(mobile.android.file.explorer.widget包中),如:
package mobile.android.file.explorer.widget;
interface MyInterface {
String getName();
}
在編譯Android工程時ADT會在gen目錄中自動生產(chǎn)MyInterface接口,直接引用該接口即可。
- Android應用程序是否可以動態(tài)引用jar文件?
JVM格式格式的jar文件不能被Android應用程序動態(tài)調(diào)用,但包含class.dex文件的jar文件可以。
打包:
jar cvf my.jar classes.dex - 如何判斷包含某個Activity Action的Android應用程序是否安裝?
調(diào)用PackageManager.queryIntentActivities方法查詢系統(tǒng)中是否注冊了某個Activity Action,如果未返回任何結(jié)果,說明系統(tǒng)中沒安裝包含指定Activity Action的apk程序。
PackageManager packageManager = getPackageManager();
Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(
intent, PackageManager.GET_INTENT_FILTERS);
if (resolveInfo.size() == 0)
Log.d("Activity Action", "Activity Action不存在");
【拓展】判斷四大應用程序組件是否安裝
1.BroadcastReceiver:(與Activity類似)
PackageManager packageManager = new PackageManager();
Intent intent = new Intent("mobile.android.MYBROADCAST");
List<ResolveInfo> resolveInfos = packageManager.queryBroadcastReceivers(
intent, PackageManager.GET_INTENT_FILTERS);
if (resolveInfos.size() == 0)
Log.d("Broadcast Action", "不存在");
2.Service(AIDL Service):AIDL Service在調(diào)用時需要使用bindService進行綁定,如果AIDL Service不存在則綁定失敗。
if (! bindService(new Intent("mobile.android.IMyService"),
serviceConnection, Context.BIND_AUTO_CREATE)) {
Log.d("AIDL Service", "不存在");
}
3.ContentProvider:根據(jù)ContentResolver對象的相應方法的返回值進行判斷。
Uri uri = Uri.parse("content://mobile.android.regioncontentprovider/cities");
Cursor cursor = getContentResolver().query(uri,
new String[] {"city_code as_id", "city_name"}, null, null, null);
if (cursor == null)
Log.d("Content Provider", "不存在");
- 在Android應用程序中Java與JavaScript如何交互?
WebView組件——可以執(zhí)行JavaScript腳本,也允許在JavaScript腳本中執(zhí)行java代碼。
1. Java執(zhí)行JavaScript腳本:
WebView webView = new WebView(this);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setWebChromeClient(new WebChromeClient());
webView.loadDataWithBaseURL(null, s, "text/html", "utf-8", null);
2.Java與JavaScript間傳遞數(shù)據(jù),JavaScript腳本執(zhí)行Java代碼:
WebView.addJavascriptInterface(new Object(){
public void move(int x, int, y) {
//Java代碼
}
}, "demo"); //demo為JavaScript中可訪問的對象,通過該對象調(diào)用move方法
在JavaScript中調(diào)用move方法:
<script language="javascript">
window.demo.move(20, 100);
</script>
【拓展】Java與JavaScript交互的傳統(tǒng)方法
在Java代碼中通過占位符替換的方式向JavaScript腳本中傳遞參數(shù)。
JavaScript代碼:
<script language="javascript">
function myFun(age, salary) {
//JavaScript腳本
};
myFun(#age#, #salary#);
</script>
將整個JavaScript腳本讀到內(nèi)存中,并將#age#和#salary#替換成相應值,再執(zhí)行JavaScript腳本。
有返回值:使用alert函數(shù)彈出一個對話框,或者在JavaScript中通過HTTP請求發(fā)送一個返回值。
請描述NDK方法的命名規(guī)則,并描述NDK方法中前兩個參數(shù)的作用。
jstring Java_調(diào)用NDK方法的java類全名_本地方法名(JNIEnv *env, jobject obj) {......}
例如:調(diào)用NDK方法的java類全名:mobile.android.HelloWorldJNI
本地方法名:process
jstring java_mobile_android_HelloWorldJNI_process(JNIEnv env, jobject obj) {......}
JNIEnv ~ 當前NDK環(huán)境的對象指針,可以通過該參數(shù)值訪問NDK中的內(nèi)置成員。
jobject ~ 調(diào)用當前NDK方法的Java對象,可以用該參數(shù)值訪問調(diào)用當前NDK方法的Java對象的成員。NDK程序怎么訪問Java類成員?
根據(jù)jobject訪問當前NDK方法的Java對象成員。
java類:
public class HelloWorldJNI extends Activity {
String name = "Jobs";
......
}
NDK代碼:
jstring Java_mobile_android_jni_helloword_HelloWorldJni_setName(JNIEnv* env, jobject obj) {
jclass cls;
jfieldID fid;
cls = (env) -> GetObjectClass(env, obj);
fid = (env) -> GetFieldID(env, cls, "name", "Ljava/lang/String");
char str;
char str1 = (char)(env) -> GetStringUTFChars(env, (env) -> GetObjectField(env, obj, fid), NULL);
str = (char) malloc(128);
memset(str, 0x0, 128);
strcpy(str, "你好");
strcat(str, str1);
return (*env) -> NewStringUTF(env, str);
}如何用Java代碼讓Android Market顯示指定的程序以使用戶方便下載?
程序直接調(diào)用內(nèi)置在手機中的Android Market程序進行下載。
通過Activity Action直接調(diào)用Android Market的窗口。
>讓Android Market直接顯示我們所期望的程序:
Uri uri = Uri.parse("market://search?q=應用名稱");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
>根據(jù)應用程序ID查找:
Uri uri = Uri.parse("market://details?id=mobile.android.library");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);請寫出安裝apk程序的代碼
Intent intent = new Intent(Intent.ACTION_VIEW);
String filePath = "/sdcard/FileExplorer.apk";
intent.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
startActivity(intent);