• android 类加载器 DexClassLoader的用法,以及引出的插件架构


    1、android 类加载器(DexClassLoader的用法),调用其他apk的类中的方法:

    方式一:

       

    然后在Host中利用下面的方式调用

    PackageManager pm = getPackageManager();
            List<ResolveInfo> resolveInfos =  pm.queryIntentActivities(new Intent("com.haili.Plugin.client") , 0);
            ResolveInfo resolveInfo = resolveInfos.get(0);
            ActivityInfo activityInfo =resolveInfo.activityInfo;
    
            String packageName = activityInfo.packageName;
            String dexPath = activityInfo.applicationInfo.sourceDir; // 目标类所在的apk或jar所在的路径,加载器将在此目录寻找目标类
            String dexOutputDir = getApplicationInfo().dataDir; // dex包含在apk或者jar文件中,因此在装载目标类的时候需要先解压,此路径就是解压的路径
            String libPath = activityInfo.applicationInfo.nativeLibraryDir;  // 目标使用的一些C、C++库的路径
    
            DexClassLoader dexClassLoader = new DexClassLoader(dexPath , dexOutputDir , libPath ,this.getClass().getClassLoader());
    
        //利用java反射原理的方式来调用
            try {
                Class clazz = dexClassLoader.loadClass(packageName+"."+ "Plugin");
                Object object =  clazz.newInstance();
                Method method = clazz.getMethod("function" , Integer.TYPE ,Integer.TYPE);
                int addResult = (int) method.invoke(object ,12 ,34);
            }catch (Exception e)
            {
    
            }

    方式二:利用插件的方式来实现:

      1 、在host中定义comm的接口如下;然后生成外部jar包,然后必须以Library的方式添加到Plugin中,若以“外部jar方式”添加,jar会作为程序的一部分打包到最终文件中,导致Plugin和Host中有2份Comm(包名和类名相同),导致冲突,发生:Class ref in pre-verified class resolved to unexpected implementation错误。

     public interface Comm
    {
      public int function(int a , int b);
    }

      2、将Plugin的class的代码修改如下:

    public class Plugin implements Comm
    {
      ...  
        public int function(int a ,int b)
        {
           return a + b ;  
        }
    }

      3 、 在Host调用的时候

     PackageManager pm = getPackageManager();
            List<ResolveInfo> resolveInfos =  pm.queryIntentActivities(new Intent("com.haili.Plugin.client") , 0);
            ResolveInfo resolveInfo = resolveInfos.get(0);
            ActivityInfo activityInfo =resolveInfo.activityInfo;
    
            String packageName = activityInfo.packageName;
            String dexPath = activityInfo.applicationInfo.sourceDir; // 目标类所在的apk或jar所在的路径,加载器将在此目录寻找目标类
            String dexOutputDir = getApplicationInfo().dataDir; // dex包含在apk或者jar文件中,因此在装载目标类的时候需要先解压,此路径就是解压的路径
            String libPath = activityInfo.applicationInfo.nativeLibraryDir;  // 目标使用的一些C、C++库的路径
    
            DexClassLoader dexClassLoader = new DexClassLoader(dexPath , dexOutputDir , libPath ,this.getClass().getClassLoader());
    
        
          //利用插件的方式调用
            try
            {
                Class clazz = dexClassLoader.loadClass(packageName+"."+ "Plugin");
                Comm comm = (Comm)clazz.newInstance();
                int addResult = comm.function(12 , 34);
    
            }catch (Exception exception)
            {
            }

     二、插件架构

      所谓插件,就是由宿主车内光线调用插件,如浏览器的插件,浏览器就是Host,调用的插件Plugin:

      由上面利用插件架构的方式实现可以得出插件的基本概率和特点:

      

    主要结构:

      1、在Host中定义相关接口Comm,生成jar包以library的方式导入到Plugin中。

      2、Plugin中要实现插件功能相关的类中实现接口Comm.

      3、在Host 中用上面的方法加载plugin的类,并调用Plugin中实现的方法。

     Note:为了知晓有哪些插件,Host中可以为每一个插件定义一个特定的action字段,每个插件定义一个activity,并在插件Plugin中AndroidMainfest.xml清单文件定义一个空的activity,action设置为Host中插件的字段:这样Host就可以根据字段查询相应的插件从而查找相应的类和方法。

    插件和宿主的兼容性,插件的res/values/string中一般都会定义一些版本号以及一些名称信息,在Host中可以通过下面方法获取:

      

  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/6667637.html
Copyright © 2020-2023  润新知