Skip to content

android 插件化开发研究

cheyiliu edited this page Apr 8, 2015 · 1 revision

引子

  • 百度云推送 遇到了一个困惑,他里面用到了plugin的思路来部署jar
  • 之前在网络上看到一些关于android插件开发的帖子,但自己没深入研究,借此机会深入理解下

网络上的例子-插件apk需要安装

思路

插件发现

  • activity增加internt-filter的action,同时插件里的activity的所有activity去掉默认的 <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> 这样插件apk在all app list中不可见。
        <activity
            android:name="com.xx.xxxxx.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.xx.xx.plugin"/>
            </intent-filter>
        </activity>
  • 通过PackageManager发现插件
        Intent intent = new Intent("com.xx.xx.plugin", null);
        pm = getPackageManager();
        pm.queryIntentActivities(intent, 0);

接口定义

  • 定义接口 (注意,在host工程里定义)
public interface IPlugin {

    public void setContext(Context context);

    public String getString(String packageName);

    public Drawable getDrawable(String name, String packageName);

}
  • 导出接口文件到jar, 右键host->export->java, jar file->select only the interface file, mark "export generated class files and resources"->next ... done

插件实现

  • 插件工程依赖于导出的接口jar, 实践证明,这个jar只能是通过插件工程的"java build path"方式导入,而不能放到libs目录下
  • 插件要实现发现机制, 见上面
  • 实现IPlugin接口
  • 例子见demo

发现加载和使用插件

  • 发现, 见上文
  • 加载, DexClassLoader loadClass()
    private IPlugin getPlugin(ResolveInfo rinfo) {
        ActivityInfo ainfo = rinfo.activityInfo;

        String packageName = ainfo.packageName;
        String dexPath = ainfo.applicationInfo.sourceDir;
        String dexOutputDir = getApplicationInfo().dataDir;
        String libPath = ainfo.applicationInfo.nativeLibraryDir;

        DexClassLoader cl = new DexClassLoader(dexPath, dexOutputDir, libPath,
                this.getClass().getClassLoader());
        try {
            Class<?> clazz = cl.loadClass(packageName + ".SelectSkin");//hard code the interface impl name, not so good!
            IPlugin plugin = (IPlugin) clazz.newInstance();
            plugin.setContext(this);
            return plugin;
        } catch (Exception e) {
        }
        return null;
    }
  • 使用
plugin.getDrawable("icon", info.activityInfo.packageName);

网络上的例子-插件apk'不'需要安装

  • TODO (和上面需要访问资源的例子类似)

商业化的插件平台

open source

小结

  • key, DexClassLoader
  • 反射

ref

Clone this wiki locally