增量更新操作详解
ONE Goal , ONE Passion !
简介:
studio中操作步骤:
第一步:定义native方法
- 直接copy两个工具类到项目中,如图1
DiffUtils文件: 生成补丁
public class DiffUtils {
/**
* 本地方法 比较路径为oldPath的apk与newPath的apk之间差异,并生成patch(补丁)包,存储于patchPath
*
*
* @return
*/
public static native int genDiff(String oldApkPath, String newApkPath,
String patchPath);
}
PatchUtils文件: 合成apk
public class PatchUtils {
/**
* native方法
* 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
* @param oldApkPath
* @param newApkPath
* @param patchPath
* @return
*/
public static native int patch(String oldApkPath, String newApkPath,
String patchPath);
}
第二步:使用javah命令生成两个.h头文件
- 找到源文件G:\andirodWorkspace\PatchDemo\app\src\main\java路径.
右键shift + 右键. 打开命令行 输入javah命令
javah com.fy.patchdemo.utils.PatchUtils javah com.fy.patchdemo.utils.DiffUtils
如图2:
第三步:新建jni目录
- 将生成两个.h头文件复制到jni目录(注意:jni和java文件在同一个目录)
- 将合成补丁的相关c文件导入jni目录中.如图3
- 编写我们定义的两个本地方法.
可是有点哥们说,不会写c代码啊! 表担心.两个c文件有现成的只要我们修改一下就行了.
特别注意:两个文件分别是diff.c patch.c文件
pathc.c文件
#include "com_fy_mypatch_apkutils_PatchUtils.h". 由于是直接copy的,所以这个头文件名要改成刚刚自己生成的
diff.c文件
#include “com_fy_mypatch_apkutils_DiffUtils.h” . 由于是直接copy的,所以这个头文件名要改成刚刚自己生成的
- 4.还要修改两个文件pathcutils.c 和 diffutils.c文件.
两个文件中的方法名,一定要修改成相对应.h文件中生成的方法名.如图:
第四步:编译生成so文件
1.在gradle.properties最后添加一句:
使用ndk开发可用
android.useDeprecatedNdk=true
2.在build.gradle(modle)中配置:
defaultConfig {
applicationId "com.fy.patchdemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
配置如下 :
ndk{
moduleName "diff" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
}
3.build-Make Project生成相应的so文件.编译后在app-build-intermediates-ndk下查看生成的文件.此时已经有ndk文件了.
第五步:代码部分
- MainActivity:
public class MainActivity extends AppCompatActivity {
private String oldapk = "mnt/sdcard/old.apk"; //当前apk文件.
private String newapk = "mnt/sdcard/new.apk";//将要更新的最新apk (一般不会出现在我们的android代码中,这里为了测试)
private String pathapk = "mnt/sdcard/path.patch"; //old.apk 与 new.apk生成的补丁文件. -----线下完成
private String complexapk = "mnt/sdcard/newapk.apk";//合并后的apk (old.apk与path.patch文件生成最新apk)
private ProgressDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setMessage("请稍后...");
}
static {
System.loadLibrary("diff");
}
public void onclick(View view) {
switch (view.getId()) {
case R.id.add: //合成apk
// dialog.show();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
PatchUtils.patch(oldapk, complexapk, pathapk);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "补丁合成完毕", Toast.LENGTH_SHORT).show();
dialog.dismiss();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///sdcard/newapk.apk"),
"application/vnd.android.package-archive");
startActivity(intent);
}
});
}
}).start();
break;
case R.id.diff://根据两个版本apk生成补丁
// dialog.show();
new Thread(new Runnable() {
@Override
public void run() {
DiffUtils.genDiff(oldapk, newapk, pathapk);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "生成补丁完成", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
}
}).start();
break;
default:
break;
}
}
}
第6步:测试
如果是测试.生成补丁.要先生成一个不同版本apk放到sd卡下,注意apk名字要和代码中一致oldapk.
如果实际开发.后台生成补丁包的名字也要和代码一致:path. 代码可以修改
第6步:测试效果
——————实际开发————————-
- 使用差分工具生成2个apk的差异文件(补丁).
工具使用: 在bsdiff工具目录下,右键+shift 打开命令行. 执行命令.即可生成补丁.
- 将生成的差异文件放到自己的服务器上
- 用户点击省流量更新,下载差分文件(补丁),放到固定的位置(比如:/mnt/sdcard/path)
- 将补丁与当前apk合并成新的apk.
//获取本应用的apk包路径
public String getSelfApkPath() {
List<ApplicationInfo> installList = getPackageManager().getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
for (int i = 0; i < installList.size(); i++) {
ApplicationInfo info=installList.get(i);
if(info.packageName.equals(getPackageName())){
return info.sourceDir;
}
}
return null;
}
- 将旧的应用删除.
附: 差分工具,以及项目demo
http://download.csdn.net/my