Android简单使用app增量更新

不讲原理,快速上手实现app增量更新

本文只是app端 手动实现新旧apk的差分包。注(apk的大版本不变,改变的只是资源版本号)

1,主模块,先引入下面cpp,配置文件(下面有资源 无需积分)

报错的话  app build 中defaultConfig  加入
 ndk {
        //选择要添加的对应 cpu 类型的 .so 库。
        abiFilters 'armeabi-v7a'
        // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
        }
externalNativeBuild {
            cmake {
                cppFlags ""
            }
            ndk {
//                    abiFilters "x86_64"
//                abiFilters "x86"
                abiFilters "armeabi-v7a"
            }
        }

2,手动打出新旧apk的差分包   

bspatch old.apk new.apk patch.patch    合并命令(这个用不到,我们直接在代码中合并)

bsdiff old.apk new.apk patch.patch  生成差分包命令

此处新apk  sourceversion值为 2,  旧的sourceversion为1(后面每次增量更新都加1)

新旧apk也得放在此目录下,才能对比生成差分包 

3,将差分包上传服务器(本文不讲,自己跟后台协商)

这里就是 把差分包上传到服务器了,比如线上生产app资源版本号如上图中的sourceversion 值为1 那么通过第二步打出 差分包1.patch,  将它上传到服务器,后面代码中需要通过接口或者读取服务端xml文件方式,获取是否有差分包和差分包版本号2  (下面是通接口演示)

4,代码中检测是否有差分包,进行合并后更新app。

资源版本号获取方法

 public static String getSourceVersion(Context context){
        try {
            InputStream inputStream = context.getAssets().open("resversion.xml");
            DocumentBuilderFactory factory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(inputStream);
            HashMap<String, String> updateInfo = new HashMap<String, String>();
            NodeList elementsByTagName = doc.getElementsByTagName("update");
            NodeList nl = elementsByTagName.item(0).getChildNodes();
            for (int i = 0; i < nl.getLength(); ++i) {
                Node item = nl.item(i);
                updateInfo.put(item.getNodeName(), item.getTextContent());
            }
            return updateInfo.get("sourceversion");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "1";
    }

接口返回了是否有差分包,资源版本号 ,以及差分包路径(我们需要下载)(当然,我们版本请求接口里面可能有 大版本更新,就需要不同情况进行判断是否大版本更新还是增量更新)

 /**
     * 补丁文件下载,合并成新apk
     *
     * @param url  服务器返回的差分包地址
     */
    public void downFile(String url) {
        String newApkPath = "newApk.apk"; //定义合并生成的新apk名称,随便取
        String patchName = mNewSourceName;//1.patch 
        String newApk =  Environment.getExternalStorageDirectory() + File.separator + newApkPath;
        String patchFilePath =  Environment.getExternalStorageDirectory() + File.separator + patchName;
        String loadPath = Environment.getExternalStorageDirectory()+File.separator;
          //弹框提示更新
        final AlertDialog builder =
                new AlertDialog.Builder(getActivity(), R.style.public_mydialog)
                        .create();
        builder.setCancelable(false);
        builder.show();
        builder.getWindow().setContentView(R.layout.public_resource_update_dialog);//设置弹出框加载的布局
        builder.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        builder.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        TextProgressBar textProgressBar = builder.getWindow().findViewById(R.id.pgb_percentage11);
        TextView tvProgressTip = builder.getWindow().findViewById(R.id.tv_progress_tip);
        Button btUpdate = builder.getWindow().findViewById(R.id.bt_update);
        ImageView ivCancel = builder.getWindow().findViewById(R.id.iv_cancel);
        ivCancel.setOnClickListener(view -> builder.dismiss());
        btUpdate.setOnClickListener(v -> {
            btUpdate.setEnabled(false);
            tvProgressTip.setText("更新中,请耐心等待...");
            textProgressBar.setVisibility(View.VISIBLE);

            Runnable runnable = () -> {
                textProgressBar.setText(mProgress +"%");
                textProgressBar.setProgress(mProgress);
            };
            DownloadUtil.get().download(url, loadPath, mNewSourceName,
                    new DownloadUtil.OnDownloadListener() {
                        @Override
                        public void onDownloadSuccess(File file) {
                            getActivity().runOnUiThread(() -> tvProgressTip.setText("更新完成,资源整合中..."));
                            //下载完成进行相关逻辑操作
                            hebing(newApk,patchFilePath, builder);
                        }

                        @Override
                        public void onDownloading(int progress) {
                            mProgress = progress;
                            getActivity().runOnUiThread(runnable);
                        }

                        @Override
                        public void onDownloadFailed(Exception e) {
                            getActivity().runOnUiThread(() -> {
                                btUpdate.setEnabled(true);
                                tvProgressTip.setText("更新失败,请检查网络是否链接!");
                                textProgressBar.setText(0+"%");
                                textProgressBar.setProgress(0);
                            });
                        }
                    });
        });
    }

    //合并旧apk 和补丁,生产新apk
    private void hebing(String newApk,String patchFilePath,AlertDialog builder) {
        //获取现在运行的apk路径
        String oldApk = getActivity().getApplicationInfo().sourceDir;
        File file = new File(patchFilePath);//补丁文件在

        if(file.exists()){
            int patchResult = PatchUtils.patch(oldApk, newApk, patchFilePath);
            if (builder != null && builder.isShowing()) {
                builder.dismiss();
            }
            if(patchResult == 0){//成功
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0安装未知应用权限
                    //先获取是否有安装未知来源应用的权限
                    boolean haveInstallPermission = getActivity().getPackageManager().canRequestPackageInstalls();
                    if (!haveInstallPermission) {//没有权限,需要前往设置权限
//                                showSetDialog(MainActivity.this);
//                        startInstallPermissionSettingActivity(getActivity());
                        Intent intent = new Intent();
                        intent.setAction(Constants.PERMISSION_ACTION_UNKNOWSOURCE);
                        getActivity().sendBroadcast(intent);
                    }else{
                        File file1 = new File(newApk);
                        UpdateAppManager.installApk(getActivity(),file1);
                    }
                }else{
                    File file1 = new File(newApk);
                    UpdateAppManager.installApk(getActivity(),file1);
                }
            }
        }
    }

 资源包里面涉及到的cpp 文件,工具类,下载方法,弹框提示布局 请下载资源  https://download.youkuaiyun.com/download/xiongtao63/20098353

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值