zoukankan      html  css  js  c++  java
  • 转-基于插件开发的Android实现流程

    原始地址: http://www.2cto.com/kf/201403/284689.html

    本文记述“柯元旦”Android内核剖析中基于类装载器的“插件”架构。

    插件的概念:

    1、插件不能独立运行,而必须运行于一个宿主程序中,即由宿主程序去调用插件程序。

    2、插件一般可以独安装。

    3、宿主程序中可以管理不同的插件,包括查看插件的数目,禁用或者使用某个插件。

    4、宿主程序应该保证插件的向下兼容性,即新版本的宿主程序可以运行较老版本的插件。

    下面详细看一下这种架构:

    1、宿主程序:

    新建Android项目PluginDevAndroid

    2、插件项目1:Plugin1

    3、插件项目2:

    4、综述:

    4.1、接口类一般定义在宿主项目中,比如本例中的IPluginDev.java

    4.2、插件项目需要应用IPluginDev时,则必须通过一个外部的jar包,并且该jar包是以Library的形式被添加到Plugin项目的build Path,而不是以“外部的”jar方式添加。

    如图:

    4.3、宿主程序想要知道系统中有哪些插件,可以定义一个Action,本例中使用的是如下action。

    这样的话,宿主程序就可以通过PackageManager类的queryIntentActivities函数查询相关的插件的列表了。

    得到了插件的PackageName,就可以访问插件的资源内容。例如:

    1
    2
    3
    4
    5
    Resources res = pm.getResourcesForApplication(packageName);
    int id = 0;
    id = res.getIdentifier(version, string, packageName);
    String version = res.getString(id);
    Log.d(hlwang, MainActivity test version is:+version);

    这段代码中,首先获取插件的Resource对象,接着得到名称为version字段的字符串id值,然后再调用getString获得该变量的值,于是宿主程序就知道插件程序中的资源内容了。

    关键代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    private void test(){
            Intent intent = new Intent(com.example.plugindevandroid.plugin,null);
            final PackageManager pm = getPackageManager();
            final List<resolveinfo> plugins = pm.queryIntentActivities(intent, 0);
             
            for(ResolveInfo r:plugins){
                ActivityInfo activityInfo = r.activityInfo;
                 
                String div = System.getProperty(path.separator);
                String packageName = activityInfo.packageName;
                String packageName0 = getPackageName();
                String dexPath = activityInfo.applicationInfo.sourceDir;
                String dexOutputDir1 = activityInfo.applicationInfo.dataDir;
                String dexOutputDir2 = getApplicationInfo().dataDir;
                String libPath = activityInfo.applicationInfo.nativeLibraryDir;
                 
                Log.d(hlwang, MainActivity test div is:+div
                        +,packageName is:+packageName
                        +,packageName0 is:+packageName0
                        +,dexPath is:+dexPath
                        +,dexOutputDir1 is:+dexOutputDir1
                        +,dexOutputDir2 is:+dexOutputDir2
                        +,libPath is:+libPath);
                 
                DexClassLoader dexCl = new DexClassLoader(dexPath, dexOutputDir2, libPath, getClassLoader());
                Log.d(hlwang, MainActivity test clazzName is:+packageName+.PluginVersion);
                try{
                    Class clazz = dexCl.loadClass(packageName+.PluginVersion);
                    IPluginDev plugin = (IPluginDev) clazz.newInstance();
                    String name = plugin.getName();
                    Log.d(hlwang, MainActivity test name is:+name);
                     
                    Resources res = pm.getResourcesForApplication(packageName);
                    int id = 0;
                    id = res.getIdentifier(version, string, packageName);
                    String version = res.getString(id);
                    Log.d(hlwang, MainActivity test version is:+version);
                     
                     
                    PluginObject p = new PluginObject();
                    p.name = name;
                    p.version = version;
                    Log.d(hlwang, MainActivity test p is:+p);
                    mList.add(p);
                }catch(Exception e){
                    Log.d(hlwang, MainActivity exception eeeeeeeeeeeee);
                    e.printStackTrace();
                }
                 
            }
            Log.d(hlwang, MainActivity test list size is:+mList.size());
            setListAdapter(new ArrayAdapter<pluginobject>(this,
                    android.R.layout.simple_list_item_1, mList));
        }</pluginobject></resolveinfo>

    这段代码中,首先得到插件的List列表。

    然后得到插件的packageName,以及插件的dexPath目录。

    再次,得到dexOutputDir目录。

    libPath一般只c/c++使用的库文件。

    DexClassLoader的参数意义:

    dexPath:插件apk或者jar包文件的路径

    dexOutputDir:将目标apk或者jar包解压的文件的存放目录。因为宿主程序只对本应用程序所在的目录由存取权限。


    运行截图:

  • 相关阅读:
    netframework webapi IogAttribute记录request参数和错误信息
    An error occurred while starting a transaction on the provider connection. See the inner exception for details.
    mvc partialView断点调试问题
    mysql 用行号rownum更新顺序号字段
    sqlserver 导入excel
    vs2017 git凭证问题
    DataTable 转换为List
    Resharper 修改命名空间
    web api解决序列化后返回标准时间带T问题
    获取当前程序的路径
  • 原文地址:https://www.cnblogs.com/feitianlee/p/4001874.html
Copyright © 2011-2022 走看看