使用Tinker与极光推送实现Android热更新

来源:互联网 发布:微分销java源码 编辑:程序博客网 时间:2024/06/10 07:53

一、Tinker平台的配置

Tinker的注册不做赘述,打开Tinker PlatformApp管理界面,新增自己的App。输入App名称新增成功之后会进入到App详情界面,这个界面左侧的appKey在下面的配置中会用到。

二、Tinker在AndroidStudio上的配置与初始化

1.配置gradle文件:

1)打开build.gradle,添加版本库与依赖包:

buildscript {    repositories {        mavenCentral()        jcenter()    }    dependencies {        classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.1.7"    }}dependencies {    。。。    provided 'com.tinkerpatch.tinker:tinker-android-anno:1.7.11'    compile 'com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.1.7'    compile 'com.android.support:multidex:1.0.1'}

2)在build.gradle所在目录下新建tinkerpatch.gradle,添加如下内容:

apply plugin: 'tinkerpatch-support'def bakPath = file("${buildDir}/bakApk/")def baseInfo = "app-1.0.2-0721-09-46-04" // 这个值是生成patch的对比包def variantName = "release"tinkerpatchSupport {    tinkerEnable = true    reflectApplication = false    autoBackupApkPath = "${bakPath}"    appKey = "your appkey"    /** 注意:appVersion是当前app的版本号,若发布新的全量包, appVersion一定要更新 **/    appVersion = "1.0.2"    def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"    def name = "${project.name}-${variantName}"    baseApkFile = "${pathPrefix}/${name}.apk"    baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"    baseResourceRFile = "${pathPrefix}/${name}-R.txt"}android {    defaultConfig {        buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"    }    signingConfigs { // 签名文件的配置        release {            try {                storeFile file("your store file")                storePassword "your store password"                keyAlias "your key alias"                keyPassword "your key password"            } catch (ex) {                throw new InvalidUserDataException(ex.toString())            }        }    }    buildTypes {        release {            signingConfig signingConfigs.release        }    }}/** 以下配置不用做修改 **/tinkerPatch {    ignoreWarning = false    useSign = 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"    }    buildConfig {        keepDexApply = false    }}

3)在build.gradle中通过apply from: 'tinkerpatch.gradle'引入tinkerpatch.gradle

2.Tinker在Android工程里的初始化

1)新建ApplicationLike文件,并在这个文件中对Tinker进行初始化配置

@SuppressWarnings("unused")public class MyApplicationLike extends DefaultApplicationLike {    private static final String TAG = "sglei-tinker";    public MyApplicationLike(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);        MultiDex.install(base);    }    @Override    public void onCreate() {        super.onCreate();        initTinker();    }    private void initTinker() {        if (BuildConfig.TINKER_ENABLE) {            TinkerPatch.init(this)                    .reflectPatchLibrary()                    .setPatchRollbackOnScreenOff(true)                    .setPatchRestartOnSrceenOff(true)                    .setFetchPatchIntervalByHours(3)                    .setPatchResultCallback(new ResultCallBack() {                        @Override                        public void onPatchResult(PatchResult patchResult) {                            Log.i(TAG, "补丁安装结果:" + patchResult.toString());                        }                    });            Log.d(TAG, "current patch version is " + TinkerPatch.with().getPatchVersion());            TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();        }    }}

2)新建自己的Application文件,这个Application继承自com.tencent.tinker.loader.app.TinkerApplication,而不是android.app.Application

public class MyApplication extends TinkerApplication {    public MyApplication() {      super(ShareConstants.TINKER_ENABLE_ALL, "com.fablesmart.pagc.MyApplicationLike");//这里修改为上面自己的ApplicationLike路径    }}

此时,Tinker的配置已经全部完成,TinkerPatch.with().fetchPatchUpdateAndPollWithInterval()会通过初始化中setFetchPatchIntervalByHours(3)设置的3小时轮询一次的频率向TinkerPlatform请求patch,如果有新的patch,便会下载与更新。若更新成功,在下一次启动App时,更新的patch会生效。

考虑到用户使用期间,我们下发了patch,如果用户使用的时间小于上面设置的interval,便很有可能执行不到请求patch的操作。为了保证patch的及时性,也就是保证用户不需要重启两次app才能完成更新,下发补丁的时候,我们使用极光推送自定义消息来通知app请求patch。

三、JPush的配置

极光推送的在AndroidStudio上的配置详见极光推送SDK集成指南
关于Tinker,我们所做的修改是新建一个接收器。代码如下:

public class MyReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        Bundle bundle = intent.getExtras();        String content = bundle.getString(JPushInterface.EXTRA_MESSAGE);        Log.d("sglei-tinker", "jpush content = " + content);    // JPush推送的消息如果包含tinker字符,便向TinkerPlatform请求patch并更新。        if (content.contains("tinker")) {            TinkerPatch.with().fetchPatchUpdate(true);        }    }}

MyRecevier在AndroidManifest的配置如下:

<receiver    android:name=".MyReceiver"    android:exported="false"    android:enabled="true">    <intent-filter>        <action android:name="cn.jpush.android.intent.REGISTRATION" />        <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />        <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />        <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />        <action android:name="cn.jpush.android.intent.CONNECTION" />        <category android:name="your application id" />    </intent-filter></receiver>

三、Tinker与JPush实现热更新的完整操作流程。

1.生成release版本的oldApk

生成apk的方法有两种:a)打开AndroidStudio的Terminal控制台,输入命令“gradlew assembleRelease”;b)打开AndroidStudio右侧的Gradle侧边栏,双击root目录下的Tasks/build/assembleRelease。
根据tinkerpatch.gradle的配置,会在app/build/bakApk目录下生成一个当前日期的app文件夹,文件夹包括release版本的apk。这个apk可以看做包含bug的签名包,也就是我们的oldApk。

2.生成Tinker补丁包

我们修复上述apk的bug,这里的修复可以修改java文件、assets与res下的资源文件等。代码与资源文件修改完成后,需要将tinkerpatch.gradle中的baseInfo改成oldApk所在的文件夹
生成patch的方法也是两种:a)打开Terminal控制台,执行“gradlew tinkerPatchRelease”;B)双击root目录下的Tasks/tinker/tinkerPatchRelease。
根据tinkerpatch.gradle的配置,会在app/build/bakApk目录下生成release版本的已修复bug的新apk,并在app/build/outputs/tinkerPatch/release文件夹下生成补丁包patch_signed.apk

3.上传Tinker补丁包并发布

1)打开TinkerPlatform的App详情页,若oldApk的版本号还未添加到该App中,点击“添加app版本”,输入版本号(这里的版本后必须和oldApk的版本号保持一致,否则oldApk读取不到我们上传到该版本的patch)。
2)点击刚刚添加的版本号,点击“选择文件”,将刚刚生成的patch_signed.apk上传,点击“提交”,该patch即上传成功。

4.JPush发送一条包含”tinker”字符的自定义消息

打开JPush控制台,创建一条自定义消息,并将发送内容填为“tinker”。发送该自定义消息。

5.重启App,patch生效

App会上面发送的自定义消息,并执行TinkerPatch.with().fetchPatchUpdate(true)
若补丁包安装成功,下次启动App的时候,oldApk所含的bug已经修复。

原创粉丝点击