国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Tinker熱修復初探

2019-11-09 15:08:02
字體:
供稿:網(wǎng)友

聽說熱修復已經(jīng)很久了,但這是第一次嘗試去應用它。所以我對其它各種熱修復也沒什么了解,這里僅僅記下如何使用Tinker熱修復。

對于Tinker熱修復的介紹和問題這里也不寫了,因為官方文檔已經(jīng)有了,戳這里進入官方介紹文檔 ,這里只記下如何在自己的項目中使用Tinker熱修復。

步驟一、 通過gradle接入Tinker

在項目的build.gradle里添加gradle依賴:

buildscript {    repositories {        jcenter()    }    dependencies {        ......        // NOTE: Do not place your application dependencies here; they belong        // in the individual module build.gradle files        classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7')    }}

在app的build.gradle里添加依賴庫及插件

dependencies {    ......    //可選,用于生成application類    

步驟二、  拷貝sample項目中app/build.gradle配置文件相關內(nèi)容

sample項目 app/build.gradle配置文件地址戳這里  

里面的內(nèi)容很多,有些內(nèi)容也許用不上,可以刪去。暫時可以把Tinker相關的配置內(nèi)容全部拷貝。

這里有一個問題需要注意:build.gradle文件中有一個方法

def getTinkerIdValue() {    return "TestTinker" + android.defaultConfig.versionName + "_" + android.defaultConfig.versionCode;    //return hasproperty("TINKER_ID") ? TINKER_ID : gitSha()} 這個方法生成TinkerId,TinkerId用來標識原始包和補丁包,也就是說給原始包打補丁的時候,原始包是通過這個TinkerId來找到補丁包的。所以這個值必須設置。

建議的設值方式是與app的版本號及版本名稱關聯(lián)起來。sample中原來的方法是通過git版本號生成,不太建議使用這種方式,因此配置中的getSha()方法也可以刪除。

步驟三、  自定義Application類

自定義一個Application類,讓他繼承DefaultApplicationLike類,如下:別忘了頂部的注解哦

@DefaultLifeCycle(application = "com.fff.xiaoqiang.testtikner.theApplication",        flags = ShareConstants.TINKER_ENABLE_ALL,        loadVerifyFlag = false)public class MyApplication extends DefaultApplicationLike {    public MyApplication(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);    }    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)    @Override    public void onBaseContextAttached(Context base) {        super.onBaseContextAttached(base);        //you must install multiDex whatever tinker is installed!        MultiDex.install(base);        TinkerInstaller.install(this,                new DefaultLoadReporter(base),                new DefaultPatchReporter(base),                new DefaultPatchListener(base),                TinkerResultService.class,                new UpgradePatch());    }    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)    public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {        getApplication().registerActivityLifecycleCallbacks(callback);    }}

其中,TinkerInstaller.install方法為初始化Tinker方法,它有兩個構造方法,如下:

    public static Tinker install(ApplicationLike applicationLike) {        ......    }    public static Tinker install(ApplicationLike applicationLike, LoadReporter loadReporter, PatchReporter patchReporter,                               PatchListener listener, Class<? extends AbstractResultService> resultServiceClass,                               AbstractPatch upgradePatchProcessor) {        ......    }

最開始的時候我是使用第一個構造方法,只需要傳入ApplicationLike這一個參數(shù)就可以了,也可以熱修復成功,但是每次修復成功后app就會被殺掉。這是因為如果使用第一個構造方法,Tinker就會使用默認參數(shù),從第二個構造方法可以看到除了ApplicationLike外初始化的時候還使用了其它五個參數(shù),他們的五個默認類分別是:

DefaultLoadReporter、 DefaultPatchReporter、 DefaultPatchListener 、DefaultTinkerResultService 和 UpgradePatch

其中DefaultTinkerResultService中能接收到熱修復的結(jié)果,查看這個類的源碼可以發(fā)現(xiàn),當修復成功后,就調(diào)用了殺掉進程的方法。因此如果不想把進程殺掉,就需要重寫這個類,修改里面的方法。

步驟四、 重寫DefaultTinkerResultService

因為我不希望修復成功后app立馬閃退,所以重寫了這個類,如下:

public class TinkerResultService extends DefaultTinkerResultService {    private static final String TAG = "TinkerResultService";    @Override    public void onPatchResult(PatchResult result) {//        super.onPatchResult(result);   把這行注釋掉,屏蔽掉父類中的方法        if (result == null) {            Log.e(TAG, "TinkerResultService received null result!!!!");            return;        }        Log.e(TAG, "TinkerResultService receive result: %s" + result.toString());        //first, we want to kill the recover process//        TinkerServiceInternals.killTinkerPatchServiceProcess(getApplicationContext());        if(result.isSuccess){    //修復成功            Log.e(TAG,"修復成功");            deleteRawPatchFile(new File(result.rawPatchFilePath));  //刪除補丁包            Log.e(TAG,"刪除補丁");        }    }}步驟五、 別忽略了Manifest.xml文件

因為手動添加了Application和Service,所以需要在Manifest.xml文件中配置上去。注意application的 name別填錯。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.fff.xiaoqiang.testtikner">    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <application        android:name=".theApplication"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/APPTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service android:name=".TinkerResultService"            android:exported="false"/>    </application></manifest>另外別忘了給app添加SD卡讀寫權限

代碼配置完成之后,就可以開始打補丁包了

首先打基礎包,也就是和我們平時打包一樣,打包完成之后,會在項目文件的build文件夾下生成一個bakApk文件夾,里面有apk、txt等文件。把這些文件的全名稱填入build.gradle配置文件中,如下:

ext {    //for some reason, you may want to ignore tinkerBuild, such as instant run debug build?    tinkerEnabled = true    //for normal build    //old apk file to build patch apk    tinkerOldApkPath = "${bakPath}/app-debug.apk"    //proguard mapping file to build patch apk    tinkerApplyMappingPath = "${bakPath}/app-debug-mapping.txt"    //resource R.txt to build patch apk, must input if there is resource changed    tinkerApplyResourcePath = "${bakPath}/app-debug-R.txt"    //only use for build all flavor, if not, just ignore this field    tinkerBuildFlavorDirectory = "${bakPath}/app-0209-19-39-45"}

tinkerOldApkPath表示原始包路徑,tinkerApplyMappingPath表示原始包mapping文件路徑,沒有的話可以不要管tinkerApplyResourcePath表示原始包資源文件路徑tinkerBuildFlavorDirectory表示使用flavor多渠道打包時,原始包文件夾路徑。如果使用了flavor多渠道打包,只需要填這一個路徑就行,上面三個可以不要管。如果沒有使用flavor多渠道打包,這個路徑也可以不要管。

基礎包打完,配置好build.gradle之后。可以試著去修改java文件中的代碼,或者修改layout資源文件等,模擬修復原始包中的bug。修改完之后,便可以使用gradle打補丁包。

因為我使用了flavor多渠道打包,所以會有這么多內(nèi)容。雙擊tinker下你需要的打補丁包版本(注意補丁包要和原始包版本一樣),就會生成補丁包了。補丁包在項目文件中的路徑為 app/build/outputs/tinkerPatch。 默認生成的補丁包擴展名是.apk,也可以改為其他類型。把補丁包放入手機sd卡下。

然后在app中觸發(fā)熱修復代碼,如下:

TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk"); 其中第二個參數(shù)為補丁包的文件路徑。注意,此方法必須在Tinker初始化完成之后調(diào)用。

一個思考: 在正式環(huán)境中,熱修復應該是這樣進行的。 后臺應該提供一個接口,每次app啟動的時候,訪問這個接口看需不需要熱修復,如果需要,后臺要返回補丁包的下載地址。app獲取到補丁包地址后開始下載補丁包到手機中,下載完成之后啟動熱修復,也就是執(zhí)行上面那句代碼。 修復完成之后,app需要重新啟動,修復才會生效。

這是第一次使用熱修復,對于Tinker也還有許多東西沒弄清楚。要投入真正的使用也許還會遇到其它許多問題,比如apk混淆等。歡迎一起交流。

幸好官方文檔已經(jīng)算比較詳細了,還有sample項目可以參考。

官方sample項目地址

官方接入指南

官方介紹以及問題匯總


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 准格尔旗| 盐城市| 崇州市| 西昌市| 嘉禾县| 奎屯市| 阿巴嘎旗| 海宁市| 绥化市| 泰州市| 湘乡市| 电白县| 阜新市| 社会| 科技| 昭平县| 揭西县| 旺苍县| 保康县| 嘉兴市| 阆中市| 达拉特旗| 衡南县| 盘山县| 舒城县| 定日县| 临朐县| 安多县| 玉龙| 潞城市| 靖江市| 定兴县| 鸡泽县| 澎湖县| 梅河口市| 邯郸县| 田东县| 涞水县| 张家口市| 五河县| 宣恩县|