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

相关文章:
1、《插件化框架 RePlugin 应用之一:配置及内置插件
2、《插件化框架 RePlugin 应用之二:内置插件的升级、卸载
3、《插件化框架 RePlugin 应用之三:外置插件

说干就干!

一、注意事项【地址

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

  • 若想改变这个行为,可以参考RePluginConfig中的 setMoveFileWhenInstalling() 方法
  • 升级插件和此等同,故不再赘述

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

3、内置插件的升级分为两种情况:主程序随包升级、通过install方法升级

  • 主程序随包升级:当用户升级了带“新版本内置插件”的主程序时,则RePlugin会在使用插件前先做升级
  • 通过install方法升级:若通过 RePlugin.install 方法做的升级(大多为用户从服务器上下载并更新),则RePlugin在调用install方法时开始做升级。当然,其规则仍遵循安装插件的规则,例如“插件运行时先不覆盖”等。

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

  • 内置插件:只要APK的时间戳和大小发生变化就升级,若两者均无变化,则不会升级。(在 RePlugin 2.1.5版本中开始支持)
  • 外置插件:只要调用 RePlugin.install 方法即可将“内置插件”转化为“外置插件”。同样的,需遵循安装插件规则。

二、准备插件的升级版本

插件的升级版本就在原先已配置好【配置方法】,并已应用的插件项目中按正常项目开发升级即可:

模拟效果前后对比:

这里写图片描述

其中,官网说“内置插件:只要APK的时间戳和大小发生变化就升级,若两者均无变化,则不会升级。”但是官网有《插件的信息》说明文档,里面用到了插件版本号这一设定,能规范化开发,所以建议采用:

这里写图片描述

然后打包,并把新包按之前的插件名修改:插件名.apk

修改完成后,放到自己服务器上,以供下载升级。【我这里用github】

三、主程序的准备及升级方法

在加入内置插件时如果有升级需求,那么之前就得有升级的逻辑代码,这里模拟插件升级,就简单地模拟把服务器中的已升级插件下载到手机,不做版本号检测什么的,下载API就直接用HttpURLConnection,模拟出效果即可,下载逻辑代码网上一大堆:

ps:如果用到6.0及以上的测试机,要动态申请读写权限。

public class UpdateService extends IntentService {

    // 插件下载地址
    String urlPath = "https://raw.githubusercontent.com/ZhangZeQiao/ImagePluginDemo/7c5866db83b57c455302fac12ea72af30d9a5364/app/src/main/assets/image.apk";
    // 插件下载后的存放路径
    String downloadDir = Environment.getExternalStorageDirectory().getAbsolutePath();

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

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        // Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
        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", "更新完成");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }
}

直接安装已下载到手机的安装包:

RePlugin.install("/***/***/image.apk");
  • 大部分情况下,应尽可能“静默升级”,以减少对用户的打扰
  • 针对升级而言,可在后台线程做一次“预加载”,提前释放Dex。具体做法:

    PluginInfo pi = RePlugin.install("/***/***/image.apk");
    if (pi != null) {
        RePlugin.preload(pi);
    }
  • 若插件没有运行,则可直接升级
  • 若插件正在运行,则会有两种场景,需分别对待:
    – 若是遇到严重问题,需要“强制升级”,则应立即提示用户,待同意后则重启进程
    – 通常情况下,建议在“锁定屏幕”后重启进程,让其在后台生效

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

这里写图片描述

四、卸载内置插件

如果插件正在运行,则不会立即卸载插件,而是将卸载诉求记录下来。直到所有“正在使用插件”的进程结束并重启后才会生效。
但是卸载只针对外置插件,由于内置插件是捆在主程序包内的,故无法卸载“内置插件”(此处有优化空间,官方还在商量对策)。

我们只能用删除的方式来“卸载”内置插件:删除内置插件非常简单,直接移除相应的Jar文件,其余均交给RePlugin来自动化完成。

  • 注意:若用户已使用了内置插件,则即便用户升级主程序,其包内已不带这个内置插件,但用户仍可继续使用它,这样可防止出现“用户升级主程序后,发现内置插件突然用不了”的情况。

demo的github地址:
https://github.com/ZhangZeQiao/RePluginUseDemo.git
https://github.com/ZhangZeQiao/ImagePluginDemo.git

猜你喜欢

转载自blog.csdn.net/zeqiao/article/details/77096913
今日推荐