編輯:關於Android編程
Android增量更新研究
很多線上的android
apk都有增量更新功能,他能使你更新app的時候,無需完全下載一個新的安裝包,而只需下載一個新舊版本之間的一個補丁(patch),然後在本地合成新的安裝包。
環境:ubuntu16.04/android
studio2.1
工具:bsdiff/bspatch
說明:http://www.daemonology.net/bsdiff/
最新版本地址:http://www.daemonology.net/bsdiff/bsdiff-4.3.tar.gz
下載後解壓:
發現是C語言寫的,需要編譯,終端打開當前路徑,輸入:make,回車:
注意:這裡的makefile有點兒問題,編譯總是報錯,需要做一些修改:
CC=gcc
LDFLAGS=
CFLAGS=-Wall
-O3 -g -lbz2
PREFIX
?= /usr/local
INSTALL_PROGRAM
?= ${INSTALL} -c -s -m 555
INSTALL_MAN
?= ${INSTALL} -c -m 444
all:
bsdiff bspatch
bsdiff:
bsdiff.c
$(CC)
bsdiff.c $(CFLAGS) $(LDFLAGS) -o bsdiff
bspatch:
bspatch.c
$(CC)
bspatch.c $(CFLAGS) $(LDFLAGS) -o bspatch
install:
${INSTALL_PROGRAM}
bsdiff bspatch ${PREFIX}/bin
.ifndef
WITHOUT_MAN
${INSTALL_MAN}
bsdiff.1 bspatch.1 ${PREFIX}/man/man1
.endif
編譯以後,生成了兩個文件:bsdiff和bspatch。
bsdiff是用於生成patch的,命令格式:bsdiff
oldfile newfile patchfile
比如,舊版本:test1.0.apk,新版本:test2.0.apk,patch文件名稱:test1.0_2.0.patch
輸入:./bsdiff
test1.0.apk test2.0.apk test1.0_2.0.patch,等待幾十秒,目錄下會生成
test1.0_2.0.patch。
以上就是生成patch包的過程,這就完成了。
--------------------------------------華麗的分割線--------------------------------------
生成patch包以後,就是合成包了。
Bspatch就是用來合成包的,語法和bsdiff一模一樣,參數順序都一樣:
bspatch
oldfile newfile
patchfile,只不過,bsdiff生成的文件是patchfile,而bspatch生成的文件是newfile。
試一下,為了區分,合成的新包,加了個”_NEW”後綴。如圖:
命令測試成功了。
下一步,我們需要在android裡實現這個功能。
因為需要用到jni,所以需要首先搭建NDK,不再介紹。
我們先計劃一下:通過更新接口,查詢時候有新版本,服務器,根據請求者的版本號,生成對應的patch包,命名規則:應用名_oldVersion-newVersion.patch,合成的新包命名:應用名_newVersion.apk,應用下載相應patch到cache目錄,如果命名符合規則,則合成新包。合成新包以後,自動安裝。
1,創建一個工程:PatchDemo:
2,創建一個新android
library
module,名字:bspatch;在bspatch模塊的main目錄下新建一個jni目錄,將bsdiff目錄裡的bspatch.c復制到jni目錄。因為項目依賴bzip2,需要自行下載bzip2,然後解壓,帶目錄復制到jni目錄,其實被依賴的只是部分文件,我並沒有一一篩選。
再看下項目結構:
3,然後回到app
module,創建類BSPatcher,聲明方法:
packagecom.zhouweixian.patchdemo.patch;
public
classBSPatcher {
static{
System.loadLibrary("bspatch");
}
public static native voidapplyPatch(String oldPath, StringnewPath, String patchPath);
}
4,打開as自帶的終端,cd
app/src/main/java/,
使用javah生成頭文件。javah
com.zhouweixian.patchdemo.patch.BSPatcher
可以看到,頭文件已經生成了,剪切到bspatch
module的jni目錄
打開bspatch.c,將main函數改一下名字,這裡改成domain了。因為不再是主函數,而是要生成.so文件,被我們的java代碼調用。
5,回到BSPatcher文件,找到裡面的applyPatch方法,正常情況下,這個函數應該顯示紅色,光標選中,代碼提示alt+enter(這個因人而異,快捷鍵可以調)如圖:
選中第一條回車,as會自動創建一個格式良好的jni方法名,在bspatch.c文件裡:
這樣代碼也就差不多了,打開app
module的build.gradle文件,添加一個NDK代碼塊:
ndk{
moduleName"bspatch"
ldLibs"log","z","m"
abiFilters"armeabi","armeabi-v7a","x86"
}
然後Build-->make
project,make完成,在bspatch
module裡,找到build/intermediates/ndk/debug/lib目錄,打開,我們發現,各個架構的.so文件都已生成:
將lib目錄下的內容復制到bspatch/jniLibs目錄下:
添加app對bspatch的依賴
到這裡,jni的工作已經沒有了,剩下的,就是如果調用bspatch的問題了。
創建一個PatchTask.java。因為生成新包的過程比較耗時,需要在工作線程中完成。
packagecom.zhouweixian.patchdemo.patch;
importandroid.os.AsyncTask;
importcom.zhouweixian.patchdemo.MyApplication;
/**
*將舊安裝包和補丁合成新安裝包,輸入參數,補丁文件路徑,合成的新包的路徑
*輸出參數,合成成功的新安裝包的路徑,如果失敗返回null
* Created by zwx on 16-10-18
*/public
classPatchTaskextendsAsyncTask{
@Override
protectedString doInBackground(String... params){
try{
String oldVersionPath =AppUtils.getOldVersionPath(MyApplication.getInstance());
BSPatcher.applyPatch(oldVersionPath, params[0],
params[1]);
returnparams[0];
}catch(Exceptione) {
e.printStackTrace();
}
return null;
}
@Override
protected voidonPostExecute(Stringstr) {
super.onPostExecute(str);
if(str
!=null){
AppUtils.install(MyApplication.getInstance(), str);
}
}
@Override
protected voidonProgressUpdate(Integer... values) {
//可能沒有明確的進度,需要提示用戶等待,成功合成新安裝包後自動安裝super.onProgressUpdate(values);
}
}
在MainActivity裡,添加一個button,在點擊事件裡,處理安裝包的合成:
@Override
public
voidonClick(View v) {
switch(v.getId()) {
caseR.id.button:
newVersion=mEditText.getText().toString();
newPatchTask().execute(PathConstant.getNewApkPath(newVersion),
PathConstant.getPatchPath(newVersion));
break;
}
}
經測試,將新安裝包放在應用的緩存目錄會導致包解析失敗,具體原因不明。
實現方式實現的方式有很多種 這裡總結最常見的幾種方式,以後再添加其他的。viewPager + RadioGroupviewPager + FragmentT
前言在自定義ViewGroup中,有時候需要實現觸摸事件攔截,比如ListView下拉刷新就是典型的觸摸事件攔截的例子。觸摸事件攔截就是在觸摸事件被parent view
首先我們看一下什麼叫做透明的進度對話框:接下來我們講一下如何創建:1、使用Eclipse創建一個新的Android 項目,使用Android
獲取到sha1後,下面開始進入百度地圖sdk的資源獲取;一、獲取密鑰和SDK;1、搜索百度地圖sdk;2、點擊獲取密鑰;3、創建應用;4、進入概述下的“相關下