当前位置: 首页 > news >正文

中国精准扶贫网站建设现状惠安规划局建设局网站

中国精准扶贫网站建设现状,惠安规划局建设局网站,wordpress网盘,龙岗 网站建设深圳信科1、介绍 我们知道PathClassLoader是一个应用的默认加载器(而且他只能加载data/app/xxx.apk的文件)#xff0c;但是我们加载插件一般使用DexClassLoader加载器#xff0c;所以这里就有问题了#xff0c;其实如果对于开始的时候#xff0c;每个人都会认为很简单#xff0c;…1、介绍 我们知道PathClassLoader是一个应用的默认加载器(而且他只能加载data/app/xxx.apk的文件)但是我们加载插件一般使用DexClassLoader加载器所以这里就有问题了其实如果对于开始的时候每个人都会认为很简单很容易想到使用DexClassLoader来加载Activity获取到class对象在使用Intent启动 2、替换LoadApk里面的mClassLoader 我们知道我们可以将我们使用的DexClassLoader加载器绑定到系统加载Activity的类加载器上就可以了这个是我们的思路。也是最重要的突破点。下面我们就来通过源码看看如何找到加载Activity的类加载器。加载Activity的时候有一个很重要的类LoadedApk.Java这个类是负责加载一个Apk程序的我们可以看一下他的源码 我们知道内部有个mClassLoader成员变量我们只需要获取它就可以了因为它不是静态的所以我们需要先获取LoadApk这个类的对象我们再去 看看ActivityThread.java这个类 我们可以发现ActivityThread里面有个静态的成员变量sCurrentActivityThread,然后还有一个ArrayMap存放Apk包名和LoadedApk映射关系的数据结构我们通过反射来获取mClassLoader对象。 如果对ActivityThread.java这个类不熟悉的可以看我这篇博客http://blog.csdn.net/u011068702/article/details/53207039 Android插件化开发之AMS与应用程序(客户端ActivityThread、Instrumentation、Activity)通信模型分析非常重要是app程序的入口处。 3、实现具体代码 1我们先需要一个测试apk,然后把这个测试的test.apk,放到手机sdcard里面去关键代码如下package com.example.testapkdemo;import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast;public class MainActivity extends ActionBarActivity {public static View parentView;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (parentView null) {setContentView(R.layout.activity_main);} else {setContentView(parentView);}findViewById(R.id.button).setOnClickListener(new OnClickListener(){Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, 我是来自插件, Toast.LENGTH_SHORT).show();}});}public void setView(View view) {this.parentView view;} } 效果图如下接下来是我宿主代码 ReflectHelper.java  这个是的我的反射帮助类 package com.example.dexclassloaderactivity;import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays;/*** 反射辅助函数* author**/ public class ReflectHelper {public static final Class?[] PARAM_TYPE_VOID new Class?[]{};public static Object invokeStaticMethod(String className, String methodName, Class?[] paramTypes, Object...params) {try {Class? clazz Class.forName(className);Method method clazz.getMethod(methodName, paramTypes);method.setAccessible(true);return method.invoke(null, params);} catch (Exception e) {e.printStackTrace();}return null;}public static Object invokeMethod(String className, String methodName, Class?[] paramTypes, Object obj, Object...params) {try {Class? clazz Class.forName(className);Method method clazz.getMethod(methodName, paramTypes);method.setAccessible(true);return method.invoke(obj, params);} catch (Exception e) {e.printStackTrace();}return null;}public static Object getStaticField(String className, String fieldName) {try {Class? clazz Class.forName(className);Field field clazz.getDeclaredField(fieldName);field.setAccessible(true);return field.get(null);} catch (Exception e) {e.printStackTrace();}return null;}public static Object getField(String className, String fieldName, Object obj) {try {Class? clazz Class.forName(className);Field field clazz.getDeclaredField(fieldName);field.setAccessible(true);return field.get(obj);} catch (Exception e) {e.printStackTrace();}return null;}public static void setStaticField(String className, String fieldName, Object value) {try {Class? clazz Class.forName(className);Field field clazz.getDeclaredField(fieldName);field.setAccessible(true);field.set(null, value);} catch (Exception e) {e.printStackTrace();}}public static void setField(String className, String fieldName, Object obj, Object value) {try {Class? clazz Class.forName(className);Field field clazz.getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);} catch (Exception e) {e.printStackTrace();}}public static Object createInstance(String className, Class?[] paramTypes, Object...params) {Object object null;try {Class? cls Class.forName(className);Constructor? constructor cls.getConstructor(paramTypes);constructor.setAccessible(true);object constructor.newInstance(params);}catch (Exception e) {e.printStackTrace();}return object;}/*** Locates a given field anywhere in the class inheritance hierarchy.** param instance an object to search the field into.* param name field name* return a field object* throws NoSuchFieldException if the field cannot be located*/public static Field findField(Object instance, String name) throws NoSuchFieldException {for (Class? clazz instance.getClass(); clazz ! null; clazz clazz.getSuperclass()) {try {Field field clazz.getDeclaredField(name);if (!field.isAccessible()) {field.setAccessible(true);}return field;} catch (NoSuchFieldException e) {// ignore and search next}}throw new NoSuchFieldException(Field name not found in instance.getClass());}/*** Locates a given field anywhere in the class inheritance hierarchy.** param cls to search the field into.* param name field name* return a field object* throws NoSuchFieldException if the field cannot be located*/public static Field findField2(Class? cls, String name) throws NoSuchFieldException {Class? clazz null;for (clazz cls; clazz ! null; clazz clazz.getSuperclass()) {try {Field field clazz.getDeclaredField(name);if (!field.isAccessible()) {field.setAccessible(true);}return field;} catch (NoSuchFieldException e) {// ignore and search next}}throw new NoSuchFieldException(Field name not found in clazz);}/*** Locates a given method anywhere in the class inheritance hierarchy.** param instance an object to search the method into.* param name method name* param parameterTypes method parameter types* return a method object* throws NoSuchMethodException if the method cannot be located*/public static Method findMethod(Object instance, String name, Class?... parameterTypes)throws NoSuchMethodException {for (Class? clazz instance.getClass(); clazz ! null; clazz clazz.getSuperclass()) {try {Method method clazz.getDeclaredMethod(name, parameterTypes);if (!method.isAccessible()) {method.setAccessible(true);}return method;} catch (NoSuchMethodException e) {// ignore and search next}}throw new NoSuchMethodException(Method name with parameters Arrays.asList(parameterTypes) not found in instance.getClass());} } MyApplication.java 这个类用实现替换mClassLoader package com.example.dexclassloaderactivity;import java.io.File; import java.lang.ref.WeakReference;import dalvik.system.DexClassLoader; import android.annotation.SuppressLint; import android.app.Application; import android.os.Environment; import android.util.ArrayMap; import android.util.Log;public class MyApplication extends Application{public static final String TAG MyApplication;public static final String AppName test.apk;public static int i 0;public static DexClassLoader mClassLoader;Overridepublic void onCreate() {Log.d(TAG, 替换之前系统的classLoader);showClassLoader();try {String cachePath this.getCacheDir().getAbsolutePath();String apkPath /*Environment.getExternalStorageState() File.separator*//sdcard/ AppName;mClassLoader new DexClassLoader(apkPath, cachePath,cachePath, getClassLoader()); loadApkClassLoader(mClassLoader);} catch (Exception e) {e.printStackTrace();}Log.d(TAG, 替换之后系统的classLoader);showClassLoader();}SuppressLint(NewApi)public void loadApkClassLoader(DexClassLoader loader) {try {Object currentActivityThread ReflectHelper.invokeMethod(android.app.ActivityThread, currentActivityThread, new Class[] {},new Object[] {});String packageName this.getPackageName();ArrayMap mpackages (ArrayMap) ReflectHelper.getField(android.app.ActivityThread, mPackages, currentActivityThread);WeakReference wr (WeakReference)mpackages.get(packageName);Log.e(TAG, mClassLoader: wr.get()); ReflectHelper.setField(android.app.LoadedApk, mClassLoader, wr.get(), loader);Log.e(TAG, load: loader); } catch (Exception e) {Log.e(TAG, load apk classloader error: Log.getStackTraceString(e)); }}/*** 打印系统的classLoader*/public void showClassLoader() {ClassLoader classLoader getClassLoader();if (classLoader ! null){Log.i(TAG, [onCreate] classLoader i : classLoader.toString());while (classLoader.getParent()!null){classLoader classLoader.getParent();Log.i(TAG,[onCreate] classLoader i : classLoader.toString());i;}}} }然后就是MainActivity.java文件里面包含了下面另外一种方式打开activity所以我把函数  inject(DexClassLoader loader)先注释掉 package com.example.dexclassloaderactivity;import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Field;import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import dalvik.system.DexClassLoader; import dalvik.system.PathClassLoader;public class MainActivity extends ActionBarActivity{public static final String TAG MainActivity;public static final String AppName test.apk;public static DexClassLoader mDexClassLoader null;public static final String APPName test.apk;public TextView mText;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.text2).setOnClickListener(new OnClickListener(){Overridepublic void onClick(View v) {try { // inject(MyApplication.mClassLoader);String apkPath Environment.getExternalStorageDirectory().toString() File.separator APPName;Class clazz MyApplication.mClassLoader.loadClass(com.example.testapkdemo.MainActivity);Intent intent new Intent(MainActivity.this, clazz);startActivity(intent);finish();} catch (Exception e) {Log.e(TAG, name: Log.getStackTraceString(e));}}});}private void inject(DexClassLoader loader){ PathClassLoader pathLoader (PathClassLoader) getClassLoader(); try { Object dexElements combineArray( getDexElements(getPathList(pathLoader)), getDexElements(getPathList(loader))); Object pathList getPathList(pathLoader); setField(pathList, pathList.getClass(), dexElements, dexElements); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static Object getPathList(Object baseDexClassLoader) throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException { ClassLoader bc (ClassLoader)baseDexClassLoader; return getField(baseDexClassLoader, Class.forName(dalvik.system.BaseDexClassLoader), pathList); } private static Object getField(Object obj, Class? cl, String field) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field localField cl.getDeclaredField(field); localField.setAccessible(true); return localField.get(obj); } private static Object getDexElements(Object paramObject) throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException { return getField(paramObject, paramObject.getClass(), dexElements); } private static void setField(Object obj, Class? cl, String field, Object value) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field localField cl.getDeclaredField(field); localField.setAccessible(true); localField.set(obj, value); } private static Object combineArray(Object arrayLhs, Object arrayRhs) { Class? localClass arrayLhs.getClass().getComponentType(); int i Array.getLength(arrayLhs); int j i Array.getLength(arrayRhs); Object result Array.newInstance(localClass, j); for (int k 0; k j; k) { if (k i) { Array.set(result, k, Array.get(arrayLhs, k)); } else { Array.set(result, k, Array.get(arrayRhs, k - i)); } } return result; } } 这里一定要注意我们犯了3个错 1、test.apk的路径写错了下次写文件路径的时候我们应该需要加上File file new File(path); 用file.exist()函数来判断是否存在 2、从sdcard卡里面读取test.apk没加上权限   uses-permission android:nameandroid.permission.READ_EXTERNAL_STORAGE/ 3、写了Application,忘了在AndroidManifest.xml文件里面声明。 我们还需要注意要加上开启activity 在AndroidManifest.xml里面注册切记希望下次不要再次犯错。 AndroidManifest.xml文件如下 ?xml version1.0 encodingutf-8? manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.example.dexclassloaderactivityandroid:versionCode1android:versionName1.0 uses-sdkandroid:minSdkVersion11android:targetSdkVersion21 /uses-permission android:nameandroid.permission.READ_EXTERNAL_STORAGE/applicationandroid:namecom.example.dexclassloaderactivity.MyApplicationandroid:allowBackuptrueandroid:icondrawable/ic_launcherandroid:labelstring/app_nameandroid:themestyle/AppTheme activityandroid:name.MainActivityandroid:labelstring/app_name intent-filteraction android:nameandroid.intent.action.MAIN /category android:nameandroid.intent.category.LAUNCHER //intent-filter/activityactivity android:namecom.example.testapkdemo.MainActivity /activity /application/manifest运行结果如下 然后这里又出现了插件资源和宿主资源冲突问题我们后面再来研究。 4、合并PathClassLoader和DexClassLoader中的dexElements数组  我们首先来看一下PathClassLoader和DexClassLoader类加载器的父类BaseDexClassloader的源码 (这里需要注意的是PathClassLoader和DexClassLoader类的父加载器是BaseClassLoader,他们的父类是BaseDexClassLoader) 这里有一个DexPathList对象在来看一下DexPathList.java源码 Elements数组我们看到这个变量他是专门存放加载的dex文件的路径的系统默认的类加载器是PathClassLoader本身一个程序加载之后会释放一个dex出来这时候会将dex路径放到里面当然DexClassLoader也是一样的那么我们会想到我们是否可以将DexClassLoader中的dexElements和PathClassLoader中的dexElements进行合并然后在设置给PathClassLoader中呢这也是一个思路。我们来看代码   /*** 以下是一种方式实现的* param loader*/ private void inject(DexClassLoader loader){PathClassLoader pathLoader (PathClassLoader) getClassLoader();try {Object dexElements combineArray(getDexElements(getPathList(pathLoader)),getDexElements(getPathList(loader)));Object pathList getPathList(pathLoader);setField(pathList, pathList.getClass(), dexElements, dexElements);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} }private static Object getPathList(Object baseDexClassLoader)throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {ClassLoader bc (ClassLoader)baseDexClassLoader;return getField(baseDexClassLoader, Class.forName(dalvik.system.BaseDexClassLoader), pathList); }private static Object getField(Object obj, Class? cl, String field)throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {Field localField cl.getDeclaredField(field);localField.setAccessible(true);return localField.get(obj); }private static Object getDexElements(Object paramObject)throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException {return getField(paramObject, paramObject.getClass(), dexElements); } private static void setField(Object obj, Class? cl, String field,Object value) throws NoSuchFieldException,IllegalArgumentException, IllegalAccessException {Field localField cl.getDeclaredField(field);localField.setAccessible(true);localField.set(obj, value); }private static Object combineArray(Object arrayLhs, Object arrayRhs) {Class? localClass arrayLhs.getClass().getComponentType();int i Array.getLength(arrayLhs);int j i Array.getLength(arrayRhs);Object result Array.newInstance(localClass, j);for (int k 0; k j; k) {if (k i) {Array.set(result, k, Array.get(arrayLhs, k));} else {Array.set(result, k, Array.get(arrayRhs, k - i));}}return result; } 然后运行的时候把MyApplication.java文件里面的函数loadApkClassLoader(mClassLoader);注释掉然后把MainActivity.java文件里面的inject(MyApplication.mClassLoader)不要注释运行效果一样。     总结 我们在使用反射机制来动态加载Activity的时候有两个思路 1、替换LoadApk类中的mClassLoader变量的值将我们动态加载类DexClassLoader设置为mClassLoader的值 2、合并系统默认加载器PathClassLoader和动态加载器DexClassLoader中的dexElements数组 这两个的思路原理都是一样的就是让我们动态加载进来的Activity能够具备正常的启动流程和生命周期。 我们还没解决资源冲突问题后面再解决有点复杂。
http://www.zqtcl.cn/news/537198/

相关文章:

  • 企业网站推广服务协议html编程语言
  • 上海知名网站建设公司合肥建设云平台证书查询
  • 网站响应度西安哪家公司做的网站好
  • 广州市白云区网站建设维护wordpress如何匹配模板
  • 360网站导航公司地址怎么做seo 优化一般包括哪些内容
  • 龙岗高端建设网站建设南京旅游网页设计
  • 企业网站优化问题wordpress滑动
  • 亳州网站建设费用广东网站建设报价
  • ai生成作文网站驾校网站源码下载
  • icon图标素材下载网站郑州做定制网站的公司
  • 网站建设培训哪家好北京有几个区几个县
  • 县局网站建设招标最新网页游戏传奇
  • 咋么做进网站跳转加群代理记账公司如何寻找客户
  • 可以做pos机的网站app网站建设制作
  • 手机移动端网站影视摄影传媒公司
  • 做化工资讯的网站湖南省做网站的
  • 廊坊哪些公司做网站做网站域名是什么意思
  • 印刷网络商城网站建设上海那家公司做响应式网站建设
  • 四川省建设厅职称查询网站购物网站页面设计
  • 网站开发导航可以进不良网站的浏览器
  • 一个中介平台网站的建设费wordpress 文章列表只显示标题
  • 网站建设包括两个方面聊城建设路小学网站
  • 怎么样做一个自己的网站遵义软件制作平台
  • 推广网站实例建设厅的证在哪里查询
  • 分类网站建设方案做学校教务处网站
  • 如何做链接淘宝客的网站只做画册的网站
  • docker可以做网站吗专业的营销型网站
  • 重庆市建设工程安全网站上海制造网站公司
  • 咨询网站公司建设计划书安卓软件开发软件
  • 手机网站建设文章直播平台开发多少钱