转-基于插件开发的Android实现流程

本文深入探讨了Android内核中基于类装载器的插件架构,包括插件的概念、宿主程序与插件项目的关系,以及如何通过接口类、Action和PackageManager查询插件列表并访问其资源内容。详细展示了如何使用DexClassLoader加载和实例化插件类,最终获取插件的名称和版本信息。

原始地址: 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包解压的文件的存放目录。因为宿主程序只对本应用程序所在的目录由存取权限。


运行截图:

\

 

转载于:https://www.cnblogs.com/feitianlee/p/4001874.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值