您的位置:首页 > 其它

插件化框架 RePlugin 应用之三:外置插件

2017-08-15 22:11 696 查看
相关文章:

1、《插件化框架 RePlugin 应用之一配置及内置插件

2、《插件化框架 RePlugin 应用之二内置插件的升级、卸载

3、《插件化框架 RePlugin 应用之三外置插件

说干就干!

外置插件的操作跟内置插件差不多。

一、插件项目的接入配置【地址

无论是内置,还是外置插件,还需理解:不是所有的APK都能作为 RePlugin 的插件并安装进来的,必须要严格按照《插件接入指南》中所述完成接入,其编译出的APK才能成为插件,且这个APK同时也可以被安装到设备中。

接入配置第 1 步:在作为插件的项目中添加 RePlugin Plugin Gradle 依赖

在项目根目录的 build.gradle(注意:不是 app/build.gradle) 中添加 replugin-plugin-gradle 依赖:

buildscript {
dependencies {
classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.1.7'
...
}
}


接入配置第 2 步:添加 RePlugin Plugin Library 依赖

在 app/build.gradle 中应用 replugin-plugin-gradle 插件,并添加 replugin-plugin-lib 依赖 :

apply plugin: 'replugin-plugin-gradle'

dependencies {
compile 'com.qihoo360.replugin:replugin-plugin-lib:2.1.7'
...
}


最后:声明插件别名、插件版本号

<!--要声明插件别名,需要在插件的AndroidManifest.xml中声明以下Meta-data:-->
<!--查看奇虎360的 RePlugin/replugin-sample/-->
<meta-data
android:name="com.qihoo360.plugin.name"
android:value="text"/>
<!--插件版本号-->
<meta-data
android:name="com.qihoo360.plugin.version.ver"
android:value="100"/>


二、注意事项【地址

1、无论安装还是升级,都会将“源文件”“移动”(而非复制)到插件的安装路径(如app_p_a)上,这样可大幅度节省安装和升级时间,但显然的,“源文件”也就会消失

若想改变这个行为,可以参考RePluginConfig中的 setMoveFileWhenInstalling() 方法

升级插件和此等同,故不再赘述

2、如果插件正在运行,则不会立即升级,而是“缓存”起来。直到所有“正在使用插件”的进程结束并重启后才会生效,升级可能会占用“内部存储空间”(因为要释放新的APK)

3、如果插件正在运行,则不会立即卸载插件,而是将卸载诉求记录下来。直到所有“正在使用插件”的进程结束并重启后才会生效

4、安装或升级失败(返回值为Null)的原因有如下几种:

是否开启了“签名校验”功能且签名不在“白名单”之中?——通常在Logcat中会出现“verifySignature: invalid cert: ”。如是,则请参考“安全与签名校验”一节,了解如何将签名加白,或关闭签名校验功能(默认为关闭)

是否将replugin-host-lib升级到2.1.4及以上?——在2.1.3及之前版本,若没有填写“meta-data”,则可能导致安装失败,返回值为null。我们在 2.1.4 版本中已经修复了此问题(卫士和其它App的所有插件都填写了meta-data,所以问题没出现)

APK安装包是否有问题?——请将“插件APK”直接安装到设备上(而非作为插件)试试。如果在设备中安装失败,则插件安装也一定是失败的。

是否没有SD卡的读写权限?——如果您的插件APK放到了SD卡上,则请务必确保主程序中拥有SD卡权限(主程序Manifest要声明,且ROM允许),否则会出现权限问题,当然,放入应用的files目录则不受影响。

设备内部存储空间是否不足?——通常出现此问题时其Logcat会出现“copyOrMoveApk: Copy/Move Failed”的警告。如是,则需要告知用户去清理手机。

5、值得注意的是,无论采用何种方式(内置/外置),均“不支持降级”,但支持“同版本覆盖”升级,也即:

内置插件:只要APK的时间戳和大小发生变化就升级,若两者均无变化,则不会升级。(在 RePlugin 2.1.5版本中开始支持)

外置插件:只要调用 RePlugin.install 方法即可将“内置插件”转化为“外置插件”。同样的,需遵循安装插件规则。

三、外置插件的安装、更新、卸载

1、修改下载Service代码逻辑

public class DownloadAndUpdateService extends IntentService {

public DownloadAndUpdateService() {
// 实现父类的构造方法,用于命名工作线程,只用于调试。
super("DownloadAndUpdateService");
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {
// Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
// 插件下载地址
String urlPath = intent.getStringExtra("urlPath");
// 插件下载后的存放路径
String downloadDir = intent.getStringExtra("downloadDir");

File file = null;
try {
URL url = new URL(urlPath);
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Charset", "UTF-8");
httpURLConnection.connect();
int fileLength = httpURLConnection.getContentLength();
String filePathUrl = httpURLConnection.getURL().getFile();
String fileFullName = filePathUrl.substring(filePathUrl.lastIndexOf(File.separatorChar) + 1);
URLConnection con = url.openConnection();
BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
String path = downloadDir + File.separatorChar + fileFullName;
file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
OutputStream out = new FileOutputStream(file);
int size = 0;
int len = 0;
byte[] buf = new byte[1024];
while ((size = bin.read(buf)) != -1) {
len += size;
out.write(buf, 0, size);
// 下载百分比
Log.v("xq", "下载了-------> " + len * 100 / fileLength);
}
bin.close();
out.close();
// 升级安装插件新版本
RePlugin.install(path);
Log.v("xq", "下载完成 : " + path);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {

}
}
}


插件按平常项目开发流程进行开发,开发修改完成后,打包成apk放到自己服务器上,以供下载升级。【我这里用github】

2、安装和更新外置插件

安装和更新都是直接安装已下载到手机的安装包:

RePlugin.install("/***/***/text.apk");


大部分情况下,应尽可能“静默升级”,以减少对用户的打扰

针对升级而言,可在后台线程做一次“预加载”,提前释放Dex。具体做法:

PluginInfo pi = RePlugin.install("/***/***/text.apk");
if (pi != null) {
RePlugin.preload(pi);
}


若插件没有运行,则可直接升级

若插件正在运行,则会有两种场景,需分别对待:

– 若是遇到严重问题,需要“强制升级”,则应立即提示用户,待同意后则重启进程

– 通常情况下,建议在“锁定屏幕”后重启进程,让其在后台生效

ps:demo时,原以为按后退键再进入就ok,但是此时还没回收,得完全退出程序后,再次进入才能升级插件。

3、卸载外置插件

要卸载插件,则需要使用 RePlugin.uninstall 方法。只需传递一个“插件名”即可:

RePlugin.uninstall("text");


注意:如果插件正在运行,则不会立即卸载插件,而是将卸载诉求记录下来。直到所有“正在使用插件”的进程结束并重启后才会生效。

demo的github地址:

https://github.com/ZhangZeQiao/RePluginUseDemo.git

https://github.com/ZhangZeQiao/ImagePluginDemo.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RePlugin 外置插件