Android Hot Update Tinker + Multi-Channel-Verpackung + detaillierte Demo des Verstärkungsprozesses
Kürzlich wurden innerhalb von zwei Monaten sechs Projekte gleichzeitig gepflegt und gestartet. Viele davon stellten kleinere Probleme dar, aber es erforderte zu viel Arbeitskraft und materielle Ressourcen, um nur aktualisierte Versionen online zu haben. Deshalb habe ich einen Tag damit verbracht, Tinker, die Open-Source-Hot-Update-Bibliothek, zu integrieren , und setzen Sie es ein. Die Lerndemo ist Open Source für Programmierer, die mit Hot Updates noch nicht vertraut sind.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
// TinkerPatch 插件
classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.1.8"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
Fügen Sie Abhängigkeiten zum Gradle in der App hinzu. Hinweis: Der obige Build-Gradle gilt für das gesamte Projekt, und der folgende Build-Gradle ist innerhalb der App.
dependencies {
// 若使用annotation需要单独引用,对于tinker的其他库都无需再引用
provided("com.tinkerpatch.tinker:tinker-android-anno:1.8.0")
compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.1.8")
}
Beachten Sie, dass Sie die Tinker-Android-Anno-Bibliothek von Tinker separat einführen müssen, wenn Sie Annotationen zum automatischen Generieren von Anwendungen verwenden. Darüber hinaus müssen wir andere Tinker-Bibliotheken nicht separat einführen.
Der Einfachheit und Bequemlichkeit halber haben wir alle TinkerPatch-bezogenen Konfigurationen in tinkerpatch.gradle abgelegt. Wir müssen es einführen:
Bewerben Sie sich über: 'tinkerpatch.gradle'
Okay, als nächstes erstellen wir dieses tinkerpatch.gradle im App-Verzeichnis, wie im Bild gezeigt:
Öffnen Sie tinkerpatch.gradle und fügen Sie alle TinkerPatch-bezogenen Konfigurationen in tinkerpatch.gradle ein.
apply plugin: 'tinkerpatch-support'
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
//基包路径
def bakPath = file("${buildDir}/bakApk/")
//基包文件夹名(打补丁包的时候,需要修改)
def baseInfo = "app-1.0.1-0221-11-01-38"
//版本名称
def variantName = "release"
/**
* 对于插件各参数的详细解析请参考
*
*/
tinkerpatchSupport {
//可以在debug的时候关闭 tinkerPatch
tinkerEnable = true
//是否使用一键接入功能 默认为false 是否反射 Application 实现一键接入;
// 一般来说,接入 Tinker 我们需要改造我们的 Application, 若这里为 true, 即我们无需对应用做任何改造即可接入。
reflectApplication = true
//将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置
autoBackupApkPath = "${bakPath}"
appKey = "582e640cae57f603"// 注意!!! 需要修改成你的appkey
/** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = "1.0.1"
protectedApp=true//使用加固
def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
def name = "${project.name}-${variantName}"
/**
* 基准包的文件路径, 对应 tinker 插件中的 oldApk 参数;编译补丁包时,
* 必需指定基准版本的 apk,默认值为空,则表示不是进行补丁包的编译
*/
baseApkFile = "${pathPrefix}/${name}.apk"
/**
* 基准包的 Proguard mapping.txt 文件路径, 对应 tinker 插件 applyMapping 参数;在编译新的 apk 时候,
* 我们希望通过保持基准 apk 的 proguard 混淆方式,
* 从而减少补丁包的大小。这是强烈推荐的,编译补丁包时,我们推荐输入基准 apk 生成的 mapping.txt 文件。
*/
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
/**
* 基准包的资源 R.txt 文件路径, 对应 tinker 插件 applyResourceMapping 参数;在编译新的apk时候,
* 我们希望通基准 apk 的 R.txt 文件来保持 Resource Id 的分配,这样不仅可以减少补丁包的大小,
* 同时也避免由于 Resource Id 改变导致 remote view 异常
*/
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
/**
* 若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
* 注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
**/
}
/**
* 用于用户在代码中判断tinkerPatch是否被使能
*/
android {
defaultConfig {
buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
}
}
/**
* 一般来说,我们无需对下面的参数做任何的修改
* 对于各参数的详细介绍请参考:
* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
ignoreWarning = false
useSign = true //是否需要签名,打正式包如果这里是true,则要配置签名,否则会编译不过去
dex {
dexMode = "jar"
pattern = ["classes*.dex"]
loader = []
}
lib {
pattern = ["lib/*/*.so"]
}
res {
pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
ignoreChange = []
largeModSize = 100
}
packageConfig {
}
sevenZip {
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
// path = "/usr/local/bin/7za"
}
buildConfig {
keepDexApply = false
}
}
Eine weitere Sache, die hier beachtet werden muss, ist der AppKey. Nachdem wir uns auf der offiziellen Website von Tinker angemeldet und eine App-Version hinzugefügt haben, müssen wir unseren eigenen AppKey in die obige Konfiguration einfügen und ein Bild anhängen.
package com.barnettwong.tinkerdemo;
import android.app.Application;
import com.tencent.tinker.loader.app.ApplicationLike;
import com.tinkerpatch.sdk.TinkerPatch;
import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike;
/**
* Created by wang on 2019-2-20.
* reflectApplication = true 时
*/
public class tinkerApplication extends Application {
private ApplicationLike tinkerApplicationLike;
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.TINKER_ENABLE) {
// 我们可以从这里获得Tinker加载过程的信息
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
// 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true);
// 每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
new FetchPatchHandler().fetchPatchWithInterval(3);
}
}
}
Fügen Sie abschließend die FetchPatchHandler-Klasse hinzu:
package com.barnettwong.tinkerdemo;
import android.os.Handler;
import android.os.Message;
import com.tinkerpatch.sdk.TinkerPatch;
/**
* Created by wang on 2019-2-20.
*/
public class FetchPatchHandler extends Handler {
public static final long HOUR_INTERVAL = 3600 * 1000;
private long checkInterval;
/**
* 通过handler, 达到按照时间间隔轮训的效果
*/
public void fetchPatchWithInterval(int hour) {
//设置TinkerPatch的时间间隔
TinkerPatch.with().setFetchPatchIntervalByHours(hour);
checkInterval = hour * HOUR_INTERVAL;
//立刻尝试去访问,检查是否有更新
sendEmptyMessage(0);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这里使用false即可
TinkerPatch.with().fetchPatchUpdate(false);
//每隔一段时间都去访问后台, 增加10分钟的buffer时间
sendEmptyMessageDelayed(0, checkInterval + 10 * 60 * 1000);
}
}
Fügen Sie abschließend die entsprechenden Netzwerk- und SD-Berechtigungen zu AndroidManifest.xml hinzu, fügen Sie android:name=".tinkerApplication" zur Anwendung hinzu und hängen Sie den Code an:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:name=".tinkerApplication"
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>
</application>
Der spezifische Verpackungs- und Patch-Veröffentlichungsprozess wird hier nicht detailliert beschrieben. Wenn Sie Fragen haben, wenden Sie sich bitte an [email protected]
Copyright 2019, wangfeng19930909
Lizenziert unter der Apache-Lizenz, Version 2.0 (die „Lizenz“). Sie dürfen diese Datei nur in Übereinstimmung mit der Lizenz verwenden. Eine Kopie der Lizenz können Sie unter http://www.apache.org/licenses/LICENSE erhalten -2.0 Sofern nicht gesetzlich vorgeschrieben oder schriftlich vereinbart, wird die im Rahmen der Lizenz vertriebene Software „WIE BESEHEN“ und OHNE JEGLICHE GEWÄHRLEISTUNGEN ODER BEDINGUNGEN, weder ausdrücklich noch stillschweigend, vertrieben spezifische Sprache, die die Berechtigungen und Einschränkungen im Rahmen der Lizenz regelt.