当前位置: 代码迷 >> Android >> android 怎么动态的加载类-app插件技术
  详细解决方案

android 怎么动态的加载类-app插件技术

热度:50   发布时间:2016-04-28 07:15:05.0
android 如何动态的加载类----app插件技术

转自:http://blog.csdn.net/mingli198611/article/details/8858076

?

前言:

?

? ? ? 在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。现如今很多项目要求需要采用类似于微信或Q游这样的插件化开发模式越来越多,本文就是阐述android的动态加载技术来满足插件化开发模式的文章。

?

1.基本概念

1.1??在Android中可以动态加载,但无法像Java中那样方便动态加载jar。

Android的虚拟机(DalvikVM)是不认识Java打出jar的byte code,需要通过dx工具来优化转换成Dalvikbyte code才行。这一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。即android要加载的java类必须dex格式的代码文件.

1.2??在Android中可以加载基于NDK的so库。

NDK的执行效率很高,加密性很好,但同时开发入门难度大,一般用于加解密、数学运算等场合。so的加载很简单,如果APK发布时已经携带了so文件,只需要在加载时调用System.loadLibrary(libName)方法即可。由于软件的安装目录中存放so的目录是没有写权限的,开发者不能更改该目录的内容,所以如果要动态加载存放在其他地方的so文件,用System.load(pathName)方法即可。

1.3??在Android中支持动态加载dex文件的两种方式:

DexClassLoader这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点

PathClassLoader只能加载已经安装到Android系统中的apk文件。也就是 /data/app 目录下的 apk 文件。其它位置的文件加载的时候都会出现 ClassNotFoundException.因为 PathClassLoader 会去读取 /data/dalvik-cache 目录下的经过 Dalvik 优化过的 dex 文件,这个目录的 dex 文件是在安装 apk 包的时候由 Dalvik 生成的。

?

2.注意

2.1 采用不用安装的插件开发模式,只能够使用?DexClassLoader进行加载.不过动态加载是有一些限制的,比如插件(子apk)包中的Activity、Service类是不能动态加载的,因为缺少声明;即使你在Manifest文件中进行了声明,系统默认也是到安装apk所在的路径中去寻找类,所以你会遇到一个ClassNotFound的异常。插件里你可以用主apk中先前放入的layout、strings等资源。但是插件中自带的界面只能用纯代码进行编写,插件中是不能加载插件(子apk)中的xml作为layout等资源使用的。所以在开发上一些特效会比较困难些,建议预先植入主apk中。

2.2?大家可以看看DexClassLoader的API文档,里面不提倡从SD卡加载,不安全

3.如何制作插件

3.1 把工程导出为jar包

3.2 执行SDK安装目录android-sdk-windows\platform-tools下的dx命令,把jar包转换为dex格式

dx?--dex?--output=dex名 jar包名

4.如何做到启动未安装的apk中的activity?

采用反射机制,把主apk中的activity的context传递到插件的activity中,然后采用反射进行回调插件activity的方法。不足之出就是,插件中的activity并不是真正的activity,它只是运行在主activity中。比如:点击返回直接退出当前activity而不是回到主activity。实例如下:

?

这是调用的Activity:

?

[java]?view plaincopy
?
?
  1. package?com.beyondsoft.activity;??
  2. ??
  3. import?java.lang.reflect.Constructor;??
  4. import?java.lang.reflect.InvocationTargetException;??
  5. import?java.lang.reflect.Method;??
  6. ??
  7. import?dalvik.system.DexClassLoader;??
  8. import?android.app.Activity;??
  9. import?android.content.pm.PackageInfo;??
  10. import?android.os.Bundle;??
  11. import?android.util.Log;??
  12. ??
  13. public?class?PlugActivity?extends?Activity?{??
  14. ??
  15. ????private?Class?mActivityClass;??
  16. ????private?Object?mActivityInstance;??
  17. ????Class?localClass;??
  18. ????private?Object?instance;??
  19. ??
  20. ????@Override??
  21. ????protected?void?onCreate(Bundle?savedInstanceState)?{??
  22. ????????super.onCreate(savedInstanceState);??
  23. ??
  24. ????????Bundle?paramBundle?=?new?Bundle();??
  25. ????????paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY",?true);??
  26. ????????paramBundle.putString("str",?"PlugActivity");??
  27. ????????String?dexpath?=?"/sdcard/FragmentProject.apk";??
  28. ????????String?dexoutputpath?=?"/mnt/sdcard/";??
  29. ????????LoadAPK(paramBundle,?dexpath,?dexoutputpath);??
  30. ????}??
  31. ??
  32. ????@Override??
  33. ????protected?void?onStart()?{??
  34. ????????super.onStart();??
  35. ????????Method?start;??
  36. ????????try?{??
  37. ????????????start?=?localClass.getMethod("onStart");??
  38. ????????????????start.invoke(instance);??
  39. ????????}?catch?(Exception?e)?{??
  40. ????????????//?TODO?Auto-generated?catch?block??
  41. ????????????e.printStackTrace();??
  42. ????????}??
  43. ????}??
  44. ??
  45. ????@Override??
  46. ????protected?void?onResume()?{??
  47. ????????//?TODO?Auto-generated?method?stub??
  48. ????????super.onResume();??
  49. ????????Method?resume;??
  50. ????????try?{??
  51. ????????????resume?=?localClass.getMethod("onResume");??
  52. ????????????resume.invoke(instance);??
  53. ????????}?catch?(Exception?e)?{??
  54. ????????????//?TODO?Auto-generated?catch?block??
  55. ????????????e.printStackTrace();??
  56. ????????}??
  57. ????}??
  58. ??
  59. ????@Override??
  60. ????protected?void?onPause()?{??
  61. ????????super.onPause();??
  62. ????????Method?pause;??
  63. ????????try?{??
  64. ????????????pause?=?localClass.getMethod("onPause");??
  65. ????????????pause.invoke(instance);??
  66. ????????}?catch?(Exception?e)?{??
  67. ????????????e.printStackTrace();??
  68. ????????}??
  69. ????}??
  70. ??
  71. ????@Override??
  72. ????protected?void?onStop()?{??
  73. ????????super.onStop();??
  74. ????????try?{??
  75. ????????????Method?stop?=?localClass.getMethod("onStop");??
  76. ????????????stop.invoke(instance);??
  77. ????????}?catch?(Exception?e)?{??
  78. ????????????e.printStackTrace();??
  79. ????????}??
  80. ????}??
  81. ??
  82. ????@Override??
  83. ????protected?void?onDestroy()?{??
  84. ????????//?TODO?Auto-generated?method?stub??
  85. ????????super.onDestroy();??
  86. ????????try?{??
  87. ????????????Method?des?=?localClass.getMethod("onDestroy");??
  88. ????????????des.invoke(instance);??
  89. ????????}?catch?(Exception?e)?{??
  90. ????????????//?TODO?Auto-generated?catch?block??
  91. ????????????e.printStackTrace();??
  92. ????????}??
  93. ????}??
  94. ??
  95. ????public?void?LoadAPK(Bundle?paramBundle,?String?dexpath,?String?dexoutputpath)?{??
  96. ????????ClassLoader?localClassLoader?=?ClassLoader.getSystemClassLoader();??
  97. ????????DexClassLoader?localDexClassLoader?=?new?DexClassLoader(dexpath,?dexoutputpath,?null,?localClassLoader);??
  98. ????????try?{??
  99. ????????????PackageInfo?plocalObject?=?getPackageManager().getPackageArchiveInfo(dexpath,?1);??
  100. ??
  101. ????????????if?((plocalObject.activities?!=?null)?&&?(plocalObject.activities.length?>?0))?{??
  102. ????????????????String?activityname?=?plocalObject.activities[0].name;??
  103. ????????????????Log.d("sys",?"activityname?=?"?+?activityname);??
  104. ??
  105. ????????????????localClass?=?localDexClassLoader.loadClass(activityname);//结果:"com.example.fragmentproject.FristActivity"??
  106. ????????????????mActivityClass?=?localClass;??
  107. ????????????????Constructor?localConstructor?=?localClass.getConstructor(new?Class[]?{});??
  108. ????????????????instance?=?localConstructor.newInstance(new?Object[]?{});??
  109. ????????????????Log.d("sys",?"instance?=?"?+?instance);??
  110. ????????????????mActivityInstance?=?instance;??
  111. ??
  112. ????????????????Method?des?=?localClass.getMethod("test");??
  113. ????????????????des.invoke(instance);??
  114. ??????????????????
  115. ????????????????Method?localMethodSetActivity?=?localClass.getDeclaredMethod("setActivity",?new?Class[]?{?Activity.class?});??
  116. ????????????????localMethodSetActivity.setAccessible(true);??
  117. ????????????????localMethodSetActivity.invoke(instance,?new?Object[]?{?this?});??
  118. ??
  119. ?????????????????Method?methodonCreate?=?localClass.getDeclaredMethod("onCreate",?new?Class[]?{?Bundle.class?});??
  120. ?????????????????methodonCreate.setAccessible(true);??
  121. ?????????????????methodonCreate.invoke(instance,?paramBundle);??
  122. ????????????}??
  123. ????????????return;??
  124. ????????}?catch?(Exception?ex)?{??
  125. ????????????ex.printStackTrace();??
  126. ????????}??
  127. ????}??
  128. ??
  129. }??

?

?

这是被调用的Activity:

?

[java]?view plaincopy
?
?
  1. public?class?FristActivity?extends?Activity{??
  2. ??
  3. ????private?Button?fragment;??
  4. ????private?Button?listFragment;??
  5. ????private?Button?controlFragment;??
  6. ????private?Button?viewFlipper;??
  7. ????private?Button?viewPager;??
  8. ????private?Activity?otherActivity;??
  9. ??
  10. ????public?void?test()?{??
  11. ????????Log.i("sys",?"测试方法执行了");??
  12. ????}??
  13. ??
  14. ????@Override??
  15. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  16. ????????super.onCreate(savedInstanceState);??
  17. ?????????//?测试DexClassLoader?动态加载未安装Apk中的类??
  18. ????????TextView?t?=?new?TextView(otherActivity);??
  19. ????????t.setText("我是测试");??
  20. ????????otherActivity.setContentView(t);//?R.layout.frist_activity_main??
  21. ??
  22. ????????Log.i("sys",?"Fragment项目启动了");??
  23. ????}??
  24. ??
  25. ????public?void?setActivity(Activity?paramActivity)?{??
  26. ????????Log.d("sys",?"setActivity..."?+?paramActivity);??
  27. ????????this.otherActivity?=?paramActivity;??
  28. ????}??
  29. ??
  30. ????@Override??
  31. ????public?void?onSaveInstanceState(Bundle?outState)?{??
  32. ????????super.onSaveInstanceState(outState);??
  33. ????????Log.i("sys",?"OnSaveInstance被调了");??
  34. ????}??
  35. ??
  36. ????@Override??
  37. ????public?void?onStart()?{??
  38. ????????Log.i("sys",?"onStart被调了");??
  39. ????????//?TODO?Auto-generated?method?stub??
  40. ????????super.onStart();??
  41. ????}??
  42. ??
  43. ????@Override??
  44. ????public?void?onResume()?{??
  45. ????????Log.i("sys",?"onResume被调了");??
  46. ????????//?TODO?Auto-generated?method?stub??
  47. ????????super.onResume();??
  48. ????}??
  49. ??
  50. ????@Override??
  51. ????public?void?onPause()?{??
  52. ????????Log.i("sys",?"onPause被调了");??
  53. ????????//?TODO?Auto-generated?method?stub??
  54. ????????super.onPause();??
  55. ????}??
  56. ??
  57. ????@Override??
  58. ????public?void?onStop()?{??
  59. ????????Log.i("sys",?"onStop被调了");??
  60. ????????//?TODO?Auto-generated?method?stub??
  61. ????????super.onStop();??
  62. ????}??
  63. ??
  64. ????@Override??
  65. ????protected?void?onDestroy()?{??
  66. ????????Log.i("sys",?"onDestroy被调了");??
  67. ????????//?TODO?Auto-generated?method?stub??
  68. ????????super.onDestroy();??
  69. ????}??
  70. } ?

5.参考文章

1.http://www.cnblogs.com/over140/archive/2011/11/23/2259367.html

2.http://blog.csdn.net/mirkerson/article/details/8771723

3.http://blog.csdn.net/scliu0718/article/details/8438823

4.http://www.verydemo.com/demo_c131_i24569.htmlAndroid 通过反射启动未安装的APK中的Activity的实例代码)

?

5.http://www.daimami.com/android/1217391.htmlAndroid 通过反射启动未安装的APK中的Activity的实例图形说明)

  相关解决方案