不讲原理,快速上手实现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