NDK開發(fā)基礎(chǔ)④增量更新之客戶端合并差分包

接續(xù)上篇NDK開發(fā)基礎(chǔ)③增量更新之服務(wù)器端生成差分包

前情提要

增量更新原理就是在服務(wù)器端使用bsdiff進行文件內(nèi)容比較,再使用了bzip2進行文件壓縮 肌索, 在下載APP時可以減少用戶流量 。在客戶端 特碳, 則是將下載好的拆分包與現(xiàn)有的APK進行文件合并 诚亚, 得出新的APK晕换, 再進行安裝 。

生產(chǎn)資源及工具

bsdiff --- bsdiff 生成差分包及合并差分包庫 站宗, 使用bspatch.c文件
bzip2 --- bzip2 bsdiff 依賴
服務(wù)器 --- Tomcat 7.0 (模擬網(wǎng)絡(luò)環(huán)境)放置差分包 闸准, 供APP下載
開發(fā)工具 --- Android Studio 2.2RC2 NDK開發(fā)

一 , 合并差分包

Ⅰ 提取bzip2中的源文件

bzip2

Ⅱ 將bzip2加入到Android Studio項目中

首先將工程切換到Project模式 梢灭, 將bzip2文件夾復(fù)制到cpp目錄下 夷家。因為最新的Android Studio采用的是CMake構(gòu)建工具 , 所有需要在bzip2目錄下敏释,創(chuàng)建一個CMakeLists.txt文件:

bzip2 cmake

Ⅲ 將bspatch.c復(fù)制到cpp目錄下 库快, 并將自動生成的CMakeList.txt文件拖拽到cpp目錄下 , 并添加子目錄參與編譯 钥顽。

bspatch cmake

修改了CMakeLists.txt文件的路徑之后 义屏, 需要在build.gradle中修改一下配置了:

build.gradle

并且配置一下build環(huán)境

build

Ⅳ 編寫JNI

public class BspatchJNI {

    /**
     * 合并增量文件
     * @param oldFilePath 當前APK路徑
     * @param newFilePath 合成后的新的APK路徑
     * @param patchFilePath 增量文件路徑
     */
    public static native void bspatchJNI(String oldFilePath,String newFilePath,String patchFilePath) ;

    static {
        System.loadLibrary("bspatch");
    }
}

Ⅴ 編寫C函數(shù) , 怎樣找執(zhí)行函數(shù) 蜂大, 上一篇已經(jīng)說了 闽铐, 套路都是一樣的 。

/*合并APK*/
JNIEXPORT void JNICALL
Java_com_zeno_incrementupdate_ndk_BspatchJNI_bspatchJNI(JNIEnv *env, jclass type,
                                                        jstring oldFilePath_, jstring newFilePath_,
                                                        jstring patchFilePath_) {
    const char *oldFilePath = (*env)->GetStringUTFChars(env, oldFilePath_, 0);
    const char *newFilePath = (*env)->GetStringUTFChars(env, newFilePath_, 0);
    const char *patchFilePath = (*env)->GetStringUTFChars(env, patchFilePath_, 0);


    // if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);

    int argc = 4 ;
    char* argv[4] ;
    argv[0] = "bspatch";
    argv[1] = oldFilePath;
    argv[2] = newFilePath;
    argv[3] = patchFilePath;

    bspatch_main(argc,argv);

    LOGE("MainActivity","%s","合并APK完成");

    (*env)->ReleaseStringUTFChars(env, oldFilePath_, oldFilePath);
    (*env)->ReleaseStringUTFChars(env, newFilePath_, newFilePath);
    (*env)->ReleaseStringUTFChars(env, patchFilePath_, patchFilePath);
}

需要注意的時 县爬, 在bspatch.c中是需要引入bzip2的 阳啥, 所有需要在文件頭部, 引入bzip2 :

// bzip2
#include "bzip2/bzlib.c"
#include "bzip2/crctable.c"
#include "bzip2/compress.c"
#include "bzip2/decompress.c"
#include "bzip2/randtable.c"
#include "bzip2/blocksort.c"
#include "bzip2/huffman.c"

#define LOGE(TAG,FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,TAG,FORMAT,__VA_ARGS__)

Ⅵ 使用

 class ApkUpdateTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                //1.下載差分包
                Log.e(TAG, "doInBackground: 正在下載财喳。察迟。。耳高。" );
                File patchFile = DownloadUtils.download(Constants.URL_PATCH_DOWNLOAD);

                //獲取當前應(yīng)用的apk文件/data/app/app
                String oldFile = APKUtils.getSourceApkPath(MainActivity.this, getPackageName());
                //2.合并得到最新版本的APK文件
                String newApkPath = Constants.NEW_APK_PATH;
                String patchFileAbsolutePath = patchFile.getAbsolutePath();
                BspatchJNI.bspatchJNI(oldFile, newApkPath, patchFileAbsolutePath);

                Log.d(TAG, "oldfile:"+oldFile);
                Log.d(TAG, "newfile:"+newApkPath);
                Log.d(TAG, "patchfile:"+patchFileAbsolutePath);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }

            return true;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(MainActivity.this);
            progressDialog.setTitle("正在下載...");
            progressDialog.show();
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            progressDialog.dismiss();
            //3.安裝
            if(result){
                Toast.makeText(MainActivity.this, "您正在進行無流量更新", Toast.LENGTH_SHORT).show();
                APKUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH);
            }
        }

    }

使用起來都比較簡單 扎瓶, 這里就不將代碼貼全了,篇末會給出github地址泌枪。

Ⅶ 打包

因為Android Studio使用了instant run技術(shù) 概荷, 所以使用Android Studio生成APK最好是打正式包 , 并且包中內(nèi)容要有差異性 碌燕, 然后再生成差分包 误证, 直接放置在WEB項目的WebContent根目錄下即可 。

結(jié)語

增量更新 修壕, 從服務(wù)器端到客戶端實現(xiàn) 愈捅, 要寫的代碼其實不多 , 關(guān)鍵在于使用第三方C/C++源碼的套路 慈鸠, 使用JNI技術(shù)調(diào)用C/C++函數(shù) 蓝谨, 其關(guān)鍵點就是找執(zhí)行函數(shù),通常為main函數(shù) 。NDK開發(fā)基礎(chǔ) 譬巫, 這一篇算是結(jié)尾 咖楣, 新版的Android Studio的NDK支持比較完善 , 使用了CMake進行項目構(gòu)建 芦昔,語法高亮以及語法提示 诱贿, 都做得相當?shù)暮昧?。開始下一個系列 烟零, C++開發(fā) 瘪松。

源碼

IncrementUpdate

參考

CMake Practice 百度網(wǎng)盤 密碼: 58a3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锨阿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌记罚,老刑警劉巖墅诡,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桐智,居然都是意外死亡末早,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門说庭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來然磷,“玉大人,你說我怎么就攤上這事刊驴∽怂眩” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵捆憎,是天一觀的道長舅柜。 經(jīng)常有香客問我,道長躲惰,這世上最難降的妖魔是什么致份? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮础拨,結(jié)果婚禮上氮块,老公的妹妹穿的比我還像新娘。我一直安慰自己诡宗,他們只是感情好滔蝉,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著僚焦,像睡著了一般锰提。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天立肘,我揣著相機與錄音边坤,去河邊找鬼。 笑死谅年,一個胖子當著我的面吹牛茧痒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播融蹂,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼旺订,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了超燃?” 一聲冷哼從身側(cè)響起区拳,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎意乓,沒想到半個月后樱调,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡届良,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年笆凌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片士葫。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡乞而,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慢显,到底是詐尸還是另有隱情爪模,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布鳍怨,位于F島的核電站呻右,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鞋喇。R本人自食惡果不足惜声滥,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侦香。 院中可真熱鬧落塑,春花似錦、人聲如沸罐韩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽散吵。三九已至龙考,卻和暖如春蟆肆,著一層夾襖步出監(jiān)牢的瞬間斥滤,已是汗流浹背缤灵。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工梨树, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留角塑,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓砸讳,卻偏偏與公主長得像幕与,于是被迫代替她去往敵國和親速兔。 傳聞我的和親對象是個殘疾皇子坛怪,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容