Android studio3.0 命令列方式簡單整合騰訊Tinker熱修復外掛
簡介:
關於熱修復的介紹現在網上有很多,所以在此我就不過多BB,此篇部落格的特點有兩個,首先,這是一個針對Android studio3.0使用者的部落格,其次,這裡採用的是命令列的方式,這是方式在工作中並不經常使用,相反,在工作中基本都是使用gradle配置的方式,但是命令列的方式相比於gradle是簡單很多的,所以這就這是一個入門級的tinker整合,意在讓大家瞭解tinker這個相對最為全面的熱修復框架(高手請繞路,前方低能)。
1、在gradle.properties中配置我們tinker的版本。這種配置方式就相當於定義一個變數,用於指定我們匯入依賴的版本,這樣對於同一框架的多個依賴可以進行很好的版本控制。
貼上板:TINKER_VERSION=1.9.0
2、module中匯入依賴,在這裡可以看到我們剛剛定義的變數在這裡得以使用
貼上板:
//可選,用於生成application類 implementation("com.tencent.tinker:tinker-android-lib:${TINKER_VERSION}") { changing = true } //tinker的核心庫 annotationProcessor("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true } compileOnly("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true } implementation "com.android.support:multidex:1.0.2"
3、建立一個管理類,來管理我們Tinker中所有的api,方便我們的使用和以後對其他工程的植入。程式碼都有註釋,這裡就直接上程式碼了
package com.jiaxin.tinkerthree.tinker; import android.content.Context; import com.tencent.tinker.lib.tinker.Tinker; import com.tencent.tinker.lib.tinker.TinkerInstaller; import com.tencent.tinker.loader.app.ApplicationLike; /** * Created by Zzw on 2017/12/24.14:06 * * @function 對Tinker的所有api做一層封裝 */ public class TinkerManger { //判斷tinker是否已經初始化 private static boolean isInstalled = false; private static ApplicationLike mAppLike; /** * 由外部呼叫完成tinker 的初始化 * @param applicationLike */ public static void instaillTinker(ApplicationLike applicationLike){ mAppLike = applicationLike; if (isInstalled){ return; } TinkerInstaller.install(mAppLike);//完成tinker初始化 isInstalled = true; } /** * 完成patch檔案載入 * @param path */ public static void loadPatch(String path){ if (Tinker.isTinkerInstalled()){ TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), path); } } /** * 通過applicationLike獲取context * @return */ private static Context getApplicationContext(){ if (mAppLike != null){ return mAppLike.getApplication().getApplicationContext(); } return null; } }
3、根據官方的要求我們要使用ApplicationLike這個類,來生成application,所以我們這裡建立一個類來繼承他
package com.jiaxin.tinkerthree.tinker;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.support.multidex.MultiDex;
import com.tencent.tinker.anno.DefaultLifeCycle;
import com.tencent.tinker.loader.app.ApplicationLike;
import com.tencent.tinker.loader.shareutil.ShareConstants;
/**
* Created by Zzw on 2017/12/24.14:11
*/
@DefaultLifeCycle(application = ".MyTinkerApplication" ,
flags = ShareConstants.TINKER_ENABLE_ALL , loadVerifyFlag = false)
public class CustomTinkerLike extends ApplicationLike {
public CustomTinkerLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
MultiDex.install(base);//使應用支援分包
TinkerManger.instaillTinker(this);
}
}
注意這裡我們使用了 一個註解,註解中後面兩個引數可以認為是固定引數,第一個是我們指定的生成Application類的名字,這裡我們叫他"MyTinkerApplication"
以上配置都完畢後我們編譯整個工程,tinker的註解就會為我們生成一個MyTinkerApplication類。
4、清單檔案中配置
這裡的配置就是指定application為我們剛剛生成的"MyTinkerApplication",還有一個TINKER_ID的配置,這個主要是因為tinker在載入補丁檔案的時候會只能的判斷當前版本和補丁版本是否一致,如果不一致就會認為此補丁檔案無效,就不會載入,所以我們這裡做測試的話兩次apk生成的時候只要這裡不該動就好了
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jiaxin.tinkerthree">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
<!-- 此處指定application為tinker為我們生成的application -->
android:name=".tinker.MyTinkerApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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>
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
<!-- 此處為tinker配置當前的應用版本 -->
<meta-data
android:name="TINKER_ID"
android:value="tinker_id_123456"
/>
</application>
</manifest>
5、以上步驟完成後,我們tinker的配置工作基本也就完成了,接下來只要使用我們的tinker管理類,生成兩個不同版本的apk即可,這裡因為tinker是支援佈局檔案的修改的,所以我模擬了點選一個按鈕增加一個按鈕的功能, 下面是我activity中的使用,佈局就不寫了哈
package com.jiaxin.tinkerthree;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.jiaxin.tinkerthree.tinker.TinkerManger;
import java.io.File;
public class MainActivity extends AppCompatActivity {
//log key
public static final String TAG = "myLog";
//file's end name
private static final String FILE_END = ".apk";
//patch file's path
private String mPatchDir;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPatchDir = Environment.getExternalStorageDirectory().getAbsolutePath();
Log.d(TAG, "onCreate: " + mPatchDir);
File file = new File(mPatchDir);
if (file.exists()){
Toast.makeText(this, "檔案存在", Toast.LENGTH_SHORT).show();
}else{
boolean mkdirs = file.mkdir();
Toast.makeText(this, mkdirs ? "建立成功" : "建立失敗", Toast.LENGTH_SHORT).show();
}
}
/**
* @click
* @param view
* load tinker patch for application
*/
public void loadPatch(View view){
TinkerManger.loadPatch(getPathName());
}
//get tinker patch fileName
private String getPathName() {
return mPatchDir.concat("/tinker").concat(FILE_END);
}
}
6、好,接下來我們只要改變佈局檔案生成兩個版本不同的apk即可,我這裡是在新的apk中添加了一個按鈕,所以old版本的apk只有一個按鈕,用於點選載入補丁檔案,new版本的apk中在第一個按鈕的基礎上又添加了一個按鈕。
7、兩個apk版本生成成功後接下來就是生成補丁apk,我們採用的是命令列的方式,所以當然是要使用tinker為我們提供的工具,我們將所有要使用到的檔案和新舊兩個版本的apk檔案以及jks簽名檔案放在同一個目錄下(建議新建一個資料夾),然後開啟命令列工具進入該資料夾,執行jar檔案:
java -jar tinker-patch-cli-1.7.7.jar
可以看到tinker提示我們該命令需要一堆引數,可以看到新舊版本apk檔案我們已經準好了,只差一個tinker_config檔案,我們開啟這個檔案,修改其中的loader為我們的application的名字,修改issue配置為我們簽名的配置和密碼
8、配置完畢後,開啟命令列工具,指定好引數在執行剛剛的命令就可以在output資料夾中看到tinker為我們生成的apk檔案,將patch_signed.apk(簽名版的)這個檔案改為我們一開始指定的檔名稱(我這裡是tinker.apk),再將其拷貝到我們一開始指定的路徑,我這裡指定的是sd下預設路徑,安裝old版本apk整個過程就完成了~~。
9、開啟安裝好的舊版本apk,點選按鈕,程式會閃退,再次開啟就會發現後新增的按鈕就已經被新增上去了,這裡閃退不用擔心,這是tinker預設的設定,因為tinker在載入補丁檔案完畢後,不重新啟動是不會生效的。這個也可以通過配置來更改,具體可以通過檢視相關文件來實現。