Android面试简录——组件2

作者: nancymi | 来源:发表于2015-04-03 23:57 被阅读362次

    自定义组件 *

    • Android怎么动态引用组件?
      动态引用:主程序和组件是分离的,组件可以单独升级和卸载。
      静态引用:将组件和主程序一起封装在编译后的目标文件中。
      可以动态引用的组件有:未安装的apk文件、包括class.dex文件的jar文件、JavaScript脚本、四大应用程序组件(Activity,Service,BroadcastReceiver,Content Provider)。
    • 如何将可视组件封装在jar文件中以及如何通过java代码适应不同的屏幕分辨率?
      jar文件可以封装很多类型的组件,如可视组件(对Android SDK原生组件的扩展),Activity,Service,BroadcastReceiver,ContentProvider等。
      封装:直接将可视组件的.class文件放到jar文件中即可,组件使用的资源文件要放到主工程的res目录的相关子目录中。在XML布局文件中使用组件要指定全名(包名+类名)。
      在自定义可视化组件时需要考虑屏幕分辨率的问题,需要将与屏幕分辨率无关的dp或sp转换成实际的像素点:
      DisplayMetrics displayMetrics = new DisplayMetrics();
      displayMetrics.setToDefaults();
      int pixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
      dip, displayMetrics);
    • 怎么编写一个自定义可视组件?
      开发模式:
      1.扩展现有的组件。
      2.组合多种组件。
      3.可以从View继承。
    • Android支持的四大应用程序组件可以封装在jar文件中吗?使用时该注意什么?
      可以,并在Android工程中静态引用jar文件。使用时需要在AndroidManifest.xml文件中注册。
    • 如何动态装载apk文件(未安装)的类?
      //my.apk表示要动态加载的apk文件,my_temp.apk表示为了优化临时生产的apk文件
      DexFile dexFile = dalvik.system.DexFile.loadDex(
      "/sdcard/my.apk", "/sdcard/my_temp.apk", 0);
      //装载apk文件中的类并创建该类的对象实例
      Object obj = dexFile.loadClass(
      "mobile.android.file.explorer.widget.Test", null).newInstance();
      //利用反射技术获取getName方法的Method对象
      Method method = obj.getClass().getDeclaredMethod("getName", null);
      //调用类中的方法,并获取方法返回值
      String result = String.valueOf(method.invoke(obj, null));

    【拓展】强类型与aidl文件
    如果使用强类型访问apk文件中的类,一般需要将该类实现的接口提供给调用者,或者提供一个aidl文件(mobile.android.file.explorer.widget包中),如:
    package mobile.android.file.explorer.widget;
    interface MyInterface {
    String getName();
    }
    在编译Android工程时ADT会在gen目录中自动生产MyInterface接口,直接引用该接口即可。

    • Android应用程序是否可以动态引用jar文件?
      JVM格式格式的jar文件不能被Android应用程序动态调用,但包含class.dex文件的jar文件可以。
      打包:
      jar cvf my.jar classes.dex
    • 如何判断包含某个Activity Action的Android应用程序是否安装?
      调用PackageManager.queryIntentActivities方法查询系统中是否注册了某个Activity Action,如果未返回任何结果,说明系统中没安装包含指定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在调用时需要使用bindService进行绑定,如果AIDL Service不存在则绑定失败。
    if (! bindService(new Intent("mobile.android.IMyService"),
    serviceConnection, Context.BIND_AUTO_CREATE)) {
    Log.d("AIDL Service", "不存在");
    }
    3.ContentProvider:根据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组件——可以执行JavaScript脚本,也允许在JavaScript脚本中执行java代码。
      1. Java执行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间传递数据,JavaScript脚本执行Java代码:
      WebView.addJavascriptInterface(new Object(){
      public void move(int x, int, y) {
      //Java代码
      }
      }, "demo"); //demo为JavaScript中可访问的对象,通过该对象调用move方法
      在JavaScript中调用move方法:
      <script language="javascript">
      window.demo.move(20, 100);
      </script>

    【拓展】Java与JavaScript交互的传统方法
    在Java代码中通过占位符替换的方式向JavaScript脚本中传递参数。
    JavaScript代码:
    <script language="javascript">
    function myFun(age, salary) {
    //JavaScript脚本
    };
    myFun(#age#, #salary#);
    </script>
    将整个JavaScript脚本读到内存中,并将#age#和#salary#替换成相应值,再执行JavaScript脚本。
    有返回值:使用alert函数弹出一个对话框,或者在JavaScript中通过HTTP请求发送一个返回值。

    • 请描述NDK方法的命名规则,并描述NDK方法中前两个参数的作用。
      jstring Java_调用NDK方法的java类全名_本地方法名(JNIEnv *env, jobject obj) {......}
      例如:调用NDK方法的java类全名:mobile.android.HelloWorldJNI
      本地方法名:process
      jstring java_mobile_android_HelloWorldJNI_process(JNIEnv env, jobject obj) {......}
      JNIEnv
      ~ 当前NDK环境的对象指针,可以通过该参数值访问NDK中的内置成员。
      jobject ~ 调用当前NDK方法的Java对象,可以用该参数值访问调用当前NDK方法的Java对象的成员。

    • NDK程序怎么访问Java类成员?
      根据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显示指定的程序以使用户方便下载?
      程序直接调用内置在手机中的Android Market程序进行下载。
      通过Activity Action直接调用Android Market的窗口。
      >让Android Market直接显示我们所期望的程序:
      Uri uri = Uri.parse("market://search?q=应用名称");
      Intent intent = new Intent(Intent.ACTION_VIEW, uri);
      startActivity(intent);
      >根据应用程序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);


    相关文章

      网友评论

        本文标题:Android面试简录——组件2

        本文链接:https://www.haomeiwen.com/subject/lxcaxttx.html