Android增量更新

原文鏈接:https://juejin.im/post/5cbe8507f265da03ba0e2c7c#heading-5

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,然後點擊更新!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章