Android增量更新
首先增量更新應該瞭解個概念:
增量更新:在版本較近的apk升級的時候,根據兩個apk之間的差異(生成差異包),合成新的安裝包,在應用內部進行升級的一種操作(需要重新安裝apk文件)。
熱更新:在發佈的版本有BUG的時候,動態加載dex文件,在不影響apk的情況下進行修復BUG(不需要重新安裝apk文件)。
作者:筆墨Android
鏈接:https://juejin.im/post/5cbe8507f265da03ba0e2c7c
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
所以從本質上增量更新和熱更新是不同的!
本文知識點:
- android 增量更新的一些工具
- android 增量更新的配置(JNI的配置)
- android 增量更新的開發
- android 遇到的一些問題
-demo地址的分享
1. 增量更新的一些工具
所謂工欲善其事,必先利其器。所以工具是很重要的!這裏先和大家介紹一下相應的工具!!!
- 1.1 bsdiff-4.3下載地址(用於生成新的安裝包)
- 1.2 bzip2-1.0.6 用於補充bsdiff中c的缺失代碼
- 1.3 bsdiff-v4.3-win-x64 用於生成相應的差異包
增量更新工具包 [百度網盤的地址(增量更新工具 提取碼爲r1ws)]https://pan.baidu.com/s/18A_qcF4cmiRYOdES3lxvbw#list/path=%2F)
2. 增量更新的配置(JNI的配置)
配置jni的環新建一個ndk項目
2.1 導入bspatch.c文件(這個是在bsdiff-4.3中)
2.2 導入bspatch.c文件所需要的文件
需要導入那些文件呢?看看下面這段代碼(在bzip中有一個Makefile文件中的代碼):
OBJS= blocksort.o
huffman.o
crctable.o
randtable.o
compress.o
decompress.o
bzlib.o
導入後的文件示意圖
- 在導入bzlib.h文件的時候,android studio3.+和之前的有區別
//#include <bzlib.h>
//新版本只有這樣能導入
#include “bzip/bzlib.h”
- 在bspatch.c文件中有一個main方法,最好把這個名稱改成別的,防止其它c代碼也使用這個main方法,造成出錯!
2.3 配置jni環境
2.3.1 創建生成bsPath
native_lib
#include <jni.h>
#include <string>
//這個主要是爲了導入其中的方法
extern "C" {
extern int p_main(int argc, char *argv[]);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_angle_netupdatademo_MainActivity_bsPath(JNIEnv *env, jobject instance, jstring oldApk_, jstring patch_, jstring output_) {
//將java字符串轉換成char指針
const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
const char *patch = env->GetStringUTFChars(patch_, 0);
const char *output = env->GetStringUTFChars(output_, 0);
// 釋放相應的指針gc
env->ReleaseStringUTFChars(oldApk_, oldApk);
env->ReleaseStringUTFChars(patch_, patch);
env->ReleaseStringUTFChars(output_, output);
}
2.3.2 配置CMakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)
# 查找文件系統中指定模式的路徑,如/* 匹配根目錄的文件(注意路徑)
file(GLOB bzip_source ${CMAKE_SOURCE_DIR}/bzip/*.c)
# 設置本地動態庫 編譯生成動態庫
add_library(
#模塊名
native-lib
# 動態庫/分享可以
SHARED
#源文件
native-lib.cpp
#配置相應的文件引用
bspatch.c
#這個相當與別名引用,上面設置了一個別名
${bzip_source}
)
#系統庫,日誌輸出log
find_library(
log-lib
log)
#需要鏈接或者編譯的庫
target_link_libraries(
native-lib
${log-lib})
2.3.3 app的build.gradle配置相應的內容
在c++的demo中添加了相應的cpu架構的兼容
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.angle.netupdatademo"
minSdkVersion 14
targetSdkVersion 28
versionCode 1
versionName "2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
//兼容cpi架構
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
}
這裏也沒有什麼太多好說的,建議看看jni配置的一些文章!
3. 增量更新的開發
其實一般的增量更新都是在splash頁面中動態從服務器下載patch文件,放在某個文件夾下,然後通過之前安裝apk的路徑進行生成新包,最後安裝。基本上就是這個流程!
所以這裏需要解決的一些內容:
- pathc文件的生成
- old.apk安裝的路徑的獲取
- 怎麼生成新的安裝包
分解處任務就很好做了!
3.1 patch文件的生成
解壓bsdiff-v4.3-win之後會有兩個文件,直接把兩個android安裝包放進去之後,通過命令 bsdiff old.apk new.apk patch就可以生成相應的patch文件了!
3.2 old.apk安裝路徑的獲取
其實這個很簡單,一行代碼就能搞定
String oldApk = getApplicationInfo().sourceDir;
3.3 怎麼生成新的apk文件
這裏就要用到之前的那個jni方法了
#include <jni.h>
#include <string>
//這個主要是爲了導入其中的方法
extern "C" {
extern int p_main(int argc, char *argv[]);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_angle_netupdatademo_MainActivity_bsPath(JNIEnv *env, jobject instance, jstring oldApk_, jstring patch_, jstring output_) {
//將java字符串轉換成char指針
const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
const char *patch = env->GetStringUTFChars(patch_, 0);
const char *output = env->GetStringUTFChars(output_, 0);
//bspatch ,oldfile ,newfile ,patchfile
char *argv[] = {"", const_cast<char *>(oldApk), const_cast<char *>(output), const_cast<char *>(patch)};
p_main(4, argv);
// 釋放相應的指針gc
env->ReleaseStringUTFChars(oldApk_, oldApk);
env->ReleaseStringUTFChars(patch_, patch);
env->ReleaseStringUTFChars(output_, output);
}
p_main就是改的那個main方法,需要四個參數,然後強轉。這裏面其實是c的一些知識,但是代碼很好理解!
那麼接下來,就直接調用這個發方法生成一個相應的apk就可以了!!!
4. 遇到的一些問題
- 如果版本跨度太大的話,可以直接更新相應的apk安裝包。不需要差分包了!很好理解,版本跨度過大的情況,差分包和新包沒有什麼區別,不需要做差分了!
5. Demo地址
Demo地址 github
使用方法,生成一個apk(老的),然後增加內容,在生成一個apk(新的)。生成拆分包!然後把這兩個都放在sd卡的根目錄安裝老的apk,然後點擊更新!!!