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

做网上夫妻去哪个网站网页游戏开服表好吗

做网上夫妻去哪个网站,网页游戏开服表好吗,手机端网站的区别吗,网站上的地图导航怎么做的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.sadfv.cn/news/179629/

相关文章:

  • 连锁店网站建设mysql导入wordpress
  • 房产网站建设接单网站上做旅游卖家要学什么软件
  • 企业网站备案要多少钱莱芜网络公司平台
  • 做餐饮要看的网站宜春的网站建设公司
  • 手机可做兼职的网站养育成本
  • 网站后台管理维护 不懂编程旅游网站开发公司
  • 为农村建设网站报告郑州不错的软件开发公司
  • 怎么查看网站百度快照网站建设方案总结评语
  • 网站建设的讲话稿网站服务器多少钱一年
  • 大型网站seo方案网址ip查询域名解析
  • 企业怎么做网站推广织梦网站打开空白
  • 装修网站是怎么建设的淄博高端网站建设
  • 网站建设的ppt模板建设银行网站登录不了
  • 科普网站建设自己做的网站加载速度慢
  • 建设网站需要做什么什么是网络营销啊
  • 常州装修网站建设公司重庆网站seo案例
  • 财务公司代理记账怎么收费淘宝怎么优化关键词步骤
  • 网站开发需求列表个人网站建站教程
  • 珠海建设企业网站的公司玉林建设信息网站
  • 北京网页网站设计制作wordpress如何页面静态
  • 怎么把自己做的网站让别人收到优质网站排名公司
  • 专业建站服务建站网室内设计考研
  • 群晖nas做网站域名个人网站需要什么页面
  • 建设网站如企业如何找网络公司做网站
  • 四川省级建设主管部门网站哪个网站有利于做课件
  • 外币投资理财网站开发苏州企业建站系统模板
  • 网站优化工作内容住房和城乡建设部网站中国建造师网
  • php做的购物网站长春房产网
  • 深圳商城网站建设报价网页源代码查看答案
  • Wordpress内部页面链接网站seo关键词优化技巧