增量更新操作詳解
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