Tinkerを導入した後、DebugモードでInstant Runをオンにする方法

9850 ワード

「Tinker+Bugly+Jenkinsピットの道」では、Tinkerにアクセスした後、Jenkinsのいくつかのピットについて説明しています.これにより、熱修復は一段落しますが、直接Runモードで実行すると、プログラムは次のエラーを報告します.
Tinker does not support instant run mode, please trigger build by assembleDebug or disable instant run in 'File->Settings...'.

よし、TInkerを使うときはInstant Run̄□̄||を開けない
GitHubにも同じissueがあり、Tinkerを導入した後、どのようにDebugモードでInstant Runを開くか、ここで私の方法を説明し、参考にします.
1.変数タグを使用してTinkerを使用するかどうかprojectbuild.gradleファイルのextで定義された変数tinkerEnabledは、TInkerが使用されているかどうかをマークするために使用されます.コードは次のようになります.
ext {

    /**
     *     tinker    
     *    ,          
     * Jenkins    ,     
     */
    tinkerEnabled = rootProject.properties["tinkerEnable"]
    if (null == tinkerEnabled) {
        tinkerEnabled = "false"
    }
}

「Tinker+Bugly+Jenkinsピットの道」を見たことがある人は知っているはずです.当社のプロジェクトはJenkinsでパッケージ化されているので、ここではrootProject.properties["tinkerEnable"]を通じてGradleコマンドからtinkerEnabledパラメータの値を取り、スクリプトを構築するパッケージコマンドラインにこのパラメータを追加します.
sh gradlew assembleRelease -PtinkerEnable=true --stacktrace

これにより、Jenkins構築時のtinkerEnableの値がtrueであることが保証されます.開発プロセスにおいて、ローカル実行または構築apkは、tinkerEnabled = "false"を修正することによって、Tinker構築を使用するか否かを決定することができる.
2.タグ値によるTInker構築の有無の決定
次にmoduleのbuild.gradleファイルでtinkerEnabled値によりtinker-support.gradle構築プロジェクトを導入するか否かを判断し、コードは以下の通りである.
//       -tinker
if (Boolean.parseBoolean(rootProject.ext.tinkerEnabled)) {
    apply from: rootProject.file('gradle/tinker-support.gradle')
}

3.Java/Kotlinコードでタグ値でTinkerを初期化するかどうかを決定Java/Kotlinコードではgradleファイルの変数値を直接使用することはできませんが、Java/Kotlinコードでは、上記で定義したタグ量でTinkerを初期化するかどうかをどのように決定しますか?Java/Kotlinコードにもグローバル変数を定義して制御することはできないでしょう.そうすれば、ローカル開発時に変更すると2つの場所が変更され、面倒でエラーが発生する可能性があります.また、Jenkinsパッケージ時にJava/KotlinがTinkerを初期化するとは確定できません.
では、どうしましょうか.「曲線救国」の方法を考えてみましょう.BuildConfigプロパティをカスタマイズすることで解決します.まず、moduleのbuild.gradleファイルでtinkerEnabledの値をBuildConfigのカスタムプロパティに渡します.コードは次のとおりです.
android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        /** =============    BuildConfig   ========================*/
        buildConfigField "boolean", "BuildConfig", rootProject.ext.tinkerEnabled
        /** =============    BuildConfig   ========================*/
    }
}

次に、BuildConfig.BuildConfigに従ってTinkerを初期化するか否かを判定するコードをカスタムアプリケーションクラスに追加する.
package com.cy.sample

import android.app.Application
import android.content.Context
import android.widget.Toast
import com.tencent.bugly.Bugly
import com.tencent.bugly.beta.Beta
import com.tencent.bugly.beta.interfaces.BetaPatchListener
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
import java.util.*

/**
 *    。
 *
 * @author cspecialy
 * @version v1.0.0
 */
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.TINKER_ENABLE) {
            initTinker()
        }
    }

    /**
     *     Tinker
     */
    private fun initTinker() {
        //            ,   true
        Beta.enableHotfix = true
        //           ,   true
        Beta.canAutoDownloadPatch = true
        //           ,   true
        Beta.canAutoPatch = true
        //           ,   false
        Beta.canNotifyUserRestart = true
        //       
        Beta.betaPatchListener = object : BetaPatchListener {
            override fun onPatchReceived(patchFile: String) {
                Toast.makeText(getApplication(), "      $patchFile", Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadReceived(savedLength: Long, totalLength: Long) {
                Toast.makeText(getApplication(),
                        String.format(Locale.getDefault(), "%s %d%%",
                                Beta.strNotificationDownloading,
                                (if (totalLength == 0L) 0 else savedLength * 100 / totalLength).toInt()),
                        Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadSuccess(msg: String) {
                Toast.makeText(getApplication(), "      ", Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadFailure(msg: String) {
                Toast.makeText(getApplication(), "      ", Toast.LENGTH_SHORT).show()

            }

            override fun onApplySuccess(msg: String) {
                Toast.makeText(getApplication(), "      ", Toast.LENGTH_SHORT).show()
            }

            override fun onApplyFailure(msg: String) {
                Toast.makeText(getApplication(), "      ", Toast.LENGTH_SHORT).show()
            }

            override fun onPatchRollback() {

            }
        }

        //       ,   false,             “    ”,              
        Bugly.setIsDevelopmentDevice(getApplication(), true)
        //        
        // String channel = WalleChannelReader.getChannel(getApplication());
        // Bugly.setAppChannel(getApplication(), channel);
        //     SDK   ,appId      Bugly     appId
        Bugly.init(getApplication(), "2a1dc56c3a", true)
    }

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base)

        if (BuildConfig.TINKER_ENABLE) {
            //   tinker
            Beta.installTinker()
        }
    }
}

以上のコードは皆さんも気づいたと信じています.はい、私のところTInkerはenableProxyApplication = trueを使って反射代理店を開く方法です.皆さんがenableProxyApplication = falseを使うと、方向も同じです.私はここでは余計なことは言いません.皆さんは土地の都合で~~~O(∩∩)Oハハ
次に,tinkerEnabled変数の値をfalseに設定するだけで開発時にInstant Runを快適に利用できるようになる.