Android面試簡錄——組件2


自定義組件 *

  • 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);


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容