Android-Plugin-Framework集成开发
Posted 杨迈1949
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android-Plugin-Framework集成开发相关的知识,希望对你有一定的参考价值。
android-Plugin-Framework集成开发
- 项目地址:https://github.com/limpoxe/Android-Plugin-Framework
- 若想要了解插件实现原理,请见项目地址的说明,本文档只是教如何使用APF框架进行插件开发。
插件开发简易流程
宿主程序
引入并编译PluginCore核心库
- 位置:项目根目录:
- 位置:项目根目录:
Application配置。若项目中定义过Application就继承插件的,若没有就定义库中的
- 项目中未定义application,AndroidManifest.xml中Application字段如下:
- 项目中未定义application,AndroidManifest.xml中Application字段如下:
- 检查PluginCore库中的AndroidManifest.xml文件的activity,service等配置(具体配置文件中有说明)
- 资源id分配问题,解决和插件资源id冲突,此处参照PluginMain项目中的代码
- 拷贝Android-Plugin-Framework-master\\PluginMain\\public.xml文件到宿主应用(:app)根目录(和build.gradle同级)
- 拷贝下面代码到build.gradle下
tasks.whenTaskAdded task ->
if (task.name.startsWith("merge") && task.name.endsWith("Resources"))
task.doLast
copy
from(project.getProjectDir())
include 'public.xml'
String dirName = task.name.replace("merge", "").replace("Resources", "");
//这里最好再增加一个buildType判断,而不是写死Debug和Release两种
if (dirName.equals("Debug") || dirName.equals("Release"))
into("$project.buildDir/intermediates/res/merged/" + dirName.toLowerCase() + "/values/")
else if (dirName.endsWith("Debug"))
into("$project.buildDir/intermediates/res/merged/" + dirName.replace("Debug", "") + "/debug/values/")
else if (dirName.endsWith("Release"))
into("$project.buildDir/intermediates/res/merged/" + dirName.replace("Release", "") + "/release/values/")
//task.enabled = false
if (task.name.startsWith("process") && task.name.endsWith("Resources"))
task.doLast
copy
String name = task.name.replace("process", "").replace("Resources", "");
//这里最好再增加一个buildType判断,而不是写死Debug和Release两种
if (name.equals("Debug") || name.equals("Release"))
name = "resources-" + name.toLowerCase() + ".ap_";
else if (name.endsWith("Debug"))
name = "resources-" + name.replace("Debug", "") + "-debug.ap_";
else if (name.endsWith("Release"))
name = "resources-" + name.replace("Release", "") + "-release.ap_";
from("$project.buildDir/intermediates/res/")
include name
if (task.name.endsWith("DebugResources"))
into("$project.buildDir/outputs/")
rename String fileName ->
'resources-debug.ap_'
else if (task.name.endsWith("ReleaseResources"))
into("$project.buildDir/outputs/")
rename String fileName ->
'resources-release.ap_'
//task.enabled = false
注意:拷贝完成后,请删除build文件夹,然后重新编译。ps:直接rebuild会报错。若编译时还报错,请注释掉这段代码(此时R文件资源分区已分区),这个bug给作者提过,说是脚本有错,但我不知道如何修改。
- 初始化插件(未安装的apk文件) //注意读写权限
- 在需要初始化插件时,调用下面代码,参数为插件的绝对路径
PluginLoader.installPlugin(Environment.getExternalStorageDirectory().getAbsolutePath()+"/app-debug.apk");
- 在需要初始化插件时,调用下面代码,参数为插件的绝对路径
- 使用插件:
// 根据插件包名(pluginId)查询插件
PluginDescriptor pluginDescriptor = PluginLoader.getPluginDescriptorByPluginId("com.example.testfacejar");
// 得到插件中所有的activity
HashMap<String, PluginActivityInfo> activityInfos = pluginDescriptor.getActivityInfos();
for (final Map.Entry<String,PluginActivityInfo> entry: activityInfos.entrySet())
Intent intent = new Intent();
// 通过类名,启动activity,宿主可以通过intent和插件通信
intent.setClassName(MainActivity.this, entry.getKey());
intent.putExtra("testParam", "testParam");
startActivity(intent);
使用service,receiver同理。
宿主注意事项
- 更新插件,需在应用启动时(旧的插件没有运行)
- 插件权限,需由宿主程序声明
- 发布版本时,请将PluginCode中的LogUtil类的isDebug字段修改为false
宿主程序给插件一个统一的平台支持,起到管理,安装,打开插件等功能。具体的管理策略由服务器插件模块下发指令,宿主执行。宿主只负责根据指令启动对应的插件,不对插件内部做干预。
插件程序
插件程序在开发中,无特别的注意事项,和普通开发方式几乎一致。不过在研究APF框架时也发现了以下特别注意事项:
- 在插件中调用
getPackageName
方法返回的是宿主的包名,不是插件包名。插件包名请用BuildConfig.APPLICATION_ID
获取。 - 对于插件和宿主共享依赖jar包,常见的如Gson。那么插件在编译的时候就不用编译到插件中去,需要使用provided方式依赖。,以gson.jar依赖为例,在bulid.gradle中配置:
dependencies
compile files(‘libs/AudienceNetwork.jar’)
provided files(‘libs/gson-2.5.jar’)
- 插件Activity切换动画不支持使用插件自己的资源。
- 插件activity不支持透明
- 不支持插件申请权限,权限必须预埋到宿主中。
- 插件的SharedPreferences和DataBase与宿主隔离,不通用
- layout.xml中的view不能使用android:οnclick=”“方式
- 资源名称不能重复,比如常见的activity_main.xml。
插件测试通过的功能
- activity、service、receiver
以上是关于Android-Plugin-Framework集成开发的主要内容,如果未能解决你的问题,请参考以下文章