Android 集成Tinker热更新问题及脱坑

因为业务的需求不得不集成热更新,小小心得,先记下:

现在开始进入正题,集成热更新-带你跨过我所遇到过的坑:

因为刚开始的时候我的Android studio版本号是3.0.1,所以在这个过程中遇到了很多的问题,在查询了大神们的文章之后才一步步解决,文尾我会贴出大佬们的 文章链接 如有不懂请注意查看,好了废话就不说了,建议studio版本降低到2.3.3再集成,高手勿扰,可以在这里修改studio版本号,在项目工程project -> build.gradle -> dependencies:直接手动修改为2.3.3,然后sync now就可以:

然后在项目工程project -> build.gradle -> dependencies中添加远程依赖:

dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        //热更新
        // 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
    }

集成Tinker的SDK-在app文件下的build.gradle:

注:下面两条依赖的版本大家最好按照我目前发的为基准,其他低版本多少都会有些bug,如anno1.8.0 + tinpatch sdk 1.1.8巨坑bug(不报错,只是打补丁失败)

dependencies {
    ...
 
    // 若使用annotation需要单独引用,对于tinker的其他库都无需再引用
    provided("com.tinkerpatch.tinker:tinker-android-anno:1.9.8")
    compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.8")
}

接下来创建一个配置文件,在app下和build.gradle同级下创建一个文件,用以后面添加配置文件:

然后我们在app -> build.gradle里将其引入

apply from: 'tinkerpatch.gradle'

添加配置文件:

注:这里的所有参数请全部粘贴到创建的文件下:

1)baseInfo和variantName参数先按照这个放着暂时不管

2)appKey请自行登录tinker官网登录并创建应用获取即可 To:  http://www.tinkerpatch.com/

3)appVersion版本号一般对应你的versionName就行了(其实可以这么理解,appVersion和基包的版本号保持一致即可,如果你手机安装的基包版本只要修改那么这个appVersion版本号才跟着修改,其他情况这个appVersion不需要修改)

剩余参数暂时不必理会,如想深入了解 还请自行查阅..  :

apply plugin: 'tinkerpatch-support'
 
/**
 * TODO: 请按自己的需求修改为适应自己工程的参数
 */
 
//基包路径
def bakPath = file("${buildDir}/bakApk/")
//基包文件夹名(打补丁包的时候,需要修改)
def baseInfo = "app-1.0.0-0705-10-01-29"
//版本名称
def variantName = "debug"
 
/**
 * 对于插件各参数的详细解析请参考
 *
 */
tinkerpatchSupport {
    //可以在debug的时候关闭 tinkerPatch
    tinkerEnable = true
    //是否使用一键接入功能 默认为false  是否反射 Application 实现一键接入;
    // 一般来说,接入 Tinker 我们需要改造我们的 Application, 若这里为 true, 即我们无需对应用做任何改造即可接入。
    reflectApplication = true
    //将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置
    autoBackupApkPath = "${bakPath}"
    appKey = "需要修改成你的 你的!"// 注意!!!  需要修改成你的appkey
 
    /** 注意: 若发布新的全量包, appVersion一定要更新,你也可以这么理解,若发布新的基包,appVersion一       定要更新 **/
    appVersion = "1.0.0"
 
 
    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
 
    }
 
}

给大家上个大致的参数图吧:

上述步骤 配置完之后 sync编译即可

初始化TinkerPatch SDK

官方给了我们两种方式来初始化TinkerPatch SDK,第一种是reflectApplication = true 的情况,另一种reflectApplication = false的情况,今天我们说reflectApplication = true这种情况,另一种情况,大家可以到官网中看看。简单来说一下这两种情况的区别啊,当reflectApplication = true这种情况是不需要更改我们项目的Application类,而reflectApplication = false的情况是需要改动Application这个类。
创建tinkerApplication类,进行相关的配置,代码如下:

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);
        }
    }
}

再创建一个FetchPtachHnalder类用来轮训判断

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);
    }
}

最后将AndroidManifest.xml中的添加上相应的网络和SD的权限,还要在application中加上

android:name=".utils.tinkerApplication"

    <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" />

到现在tinker基本上已经集成完了,接下来我们在Main的xml里随便写个view以便区分新旧包。

<TextView
        android:layout_centerInParent="true"
        android:text="旧版本"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

写完之后在AS面板里找到Gradle点击build下的assembleDebug进行编译,完成之后在工程左侧的build查看(它会根据编译时间生成一个时间命名的文件夹且内含一个debug包):

               

生成之后,我们将此debug包安装到手机上,运行效果为我们刚才在xml里写的旧布局:

接下来,我们打补丁包(模拟修复bug)..

首先到tinkerpatch.gradle里更改咱们先前介绍的两个参数:

baseInfo:修改为上面生成的对应文件夹名(请修改为自己的,修改为刚刚生成app -> build -> backApk下的时间目录)

variantName:因为打的debug包,所以传入debug即可

//基包路径
def bakPath = file("${buildDir}/bakApk/")
//基包文件夹名(打补丁包的时候,需要修改)
def baseInfo = "app-1.0.0-0228-18-00-28"
//版本名称
def variantName = "debug"

最后,我们在xml里做些更改,之后打出差异包补丁,继续找到Gradle下的tinker目录:

编译完成之后,请到工程目录下app->outputs->查看生成的文件夹 tinkerPatch:

接下来,我们将图中选中的patch_signed_7zip.apk上传至tinker官网(发布补丁):

最后,我们拿起手机,后台结束应用之后,重新打开即可看到补丁融合成功:

到tinker官网,我们可以查看补丁下发进度及当前成功率,附图,因为我之前发布了很多原谅我的图显示的:

这个成功率大概能达到42%左右

可能会遇到的问题:当你打完补丁包的时候,使用开发者预览模式来发包的话,如果这个开发者预览模式选择打开,发现可以成功,当开发者模式关闭的时候发现更新失败了,应该考虑这个问题可能跟成功率有关也有可能是版本号的问题(个人之后使用正式包来测的):

依赖的版本号在1.9.0以下的是不支持Android版本号8.0以上的手机的:

最后吧大佬的账号贴这里:https://blog.csdn.net/qq_37199105/article/details/80923073

喷子请绕路,谢谢

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原文地址:https://blog.csdn.net/Blog_Sun/article/details/88035496

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


安装环境都很简单,就是下载工具需要在华为开发者联盟里注册,然后认证,扫码认证我这边是不可以的,人工认证需要两个工作日审核安装成功之后遇到了很多报错,网上都是可以解决的,遇到下面这个报错网上查了很多方式也解决不了,于是记录一下  找了很久,发现网上说的我都配置了,添加 allow
上传的方式有两种,第一种是通过bintray官方出的插件bintray/gradle-bintray-plugin第二种是一个国外组织开源的插件novoda/bintray-release 这里讲bintray/gradle-bintray-plugin  1.在项目根目录下的 build.gradle 添加插件依赖 dependencies{classpat
转载自: 完美解决Error:SSLpeershutdownincorrectly打开gradle文件夹下的gradle-wrapper文件修改其中的配置文件将红色区域修改为http://services.gradle.org/distributions/等待编译完成
https://www.jianshu.com/p/9220227cdfb3buildscript{ext.kotlin_version='1.2.71'repositories{google()jcenter()}dependencies{//classpath'com.android.tools.build:gradle:3.1.0-alpha09'
Markdown版本笔记我的GitHub首页我的博客我的微信我的邮箱MyAndroidBlogsbaiqiantaobaiqiantaobqt20094baiqiantao@sina.com发布库到仓库mavenjcenterJitPackMD目录目录通过AS创建aar的步骤发布到Github仓库【推荐】创建项目配置项目构建并上传上传
 跟着教程做的,已经有了JDK,直接进行后面的步骤,下载安装AndroidSDK没有FQ,教程里的网址打不开,就换了个。网址http:/ools.android-studio.org/index.php/sdk下的.exe  nextinstall然后就是漫长的等待 ……先这样吧开始下载AndroidStudio,网址http://www.and
今天更新了universal-image-loader-1.9.5.jar文件,studio死活找不到其中相关的类,上网百度试了很多办法,总算解决了,具体方法跟一篇老外的帖子的差不多,这里分享下。 解决步骤:Somethingwentwronginincrementalbuildsystem.Oneofthisshouldhelp:MenuBuild->Rebuild
https://blog.csdn.net/zxc514257857/article/details/80425711编写不易,如有转载,请声明出处:梦回河口:https://blog.csdn.net/zxc514257857/article/details/80425711报错一:Error:Unabletofindmethod'com.android.build.gradle.tasks.factory.AndroidJavaCompile.setDepe
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow                     创建兼容AndroidStudio和eclipse的AS工程虽然我的博客名叫eclipse_xu,但是我已经将
gradle跳过测试直接编译gradlebuild-xtest  根据build.gradle和setting.gradle文件生成idea项目:gradleidea  gradle这几年发展迅猛,github越来越多的项目都开始采用gradle来构建了,但是并不是所有人都对gradle很熟悉,下面的方法可以把gradle转成maven项目,前提gradle项
本地仓库配置配置环境变量GRADLE_USER_HOME,并指向你的一个本地目录,用来保存Gradle下载的依赖包。 远程仓库配置一般Gradle、maven从中央仓库mavenCentral()http:/epo1.maven.org/maven2/下载依赖包,但是在国内下载速度巨慢,我们只能使用国内的镜像。所以每个Gradle构建的项目
what:Buildtool(构建工具)是从源代码自动创建可执行应用程序的程序。构建包括将代码编译,链接和打包成可用或可执行的形式。在小项目中,开发人员通常会手动调用构建过程。这对于较大的项目来说是不实际的,在这些项目中,很难跟踪需要构建的内容,构建过程中的顺序和依赖关系。使用自动化工
说明:该示例为在windows系统下自动化部署springboot架构:springboot+github+gradle+jdk8各种配置步骤及截图说明:1、配置git,gradle及jdk  系统管理→全局工具配置  说明:其中git配置项中的PathtoGitexecutable要指到git.exe文件,maven的配置方式和gradle类似
AndoridStudio模块化开发相关配置下面以宿主APP模块和Uer_Module模块为例:第一步:在项目根目录gradle.properties配置文件中添加如下代码isNeedUserModule=true#isNeedUserModule=false 第二步在user_module中的build.gradle文件中加入了如下代码来控制此库是library还
buildtools构建工具能够帮助你创建一个可重复的、可靠的、携带的且不需要手动干预的构建。构建工具是一个可编程的工具,它能够让你以可执行和有序的任务来表达自动化需求。假设你想要编译源代码,将生成的class文件拷贝到某个目录,然后将该目录组装成可交付的软件。如下图所示,展示了所
Git及用法Git是目前世界上最先进的分布式版本控制系统。Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上
打release包的时候,出现这个玩意,但debug直接跑apk又没问题。Causedby:com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:ExpectedanamebutwasSTRINGatline1column99path$[0].apkInfo.versionNameatcom.google.gson.internal.bind.
android\gradle\wrapper\gradle-wrapper.properties由distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=https\://services.gradle.org/distributions/gradle-2.12.1-all.
1.上传本地仓库1.1build.gradle项目设置plugins{id'java'id'maven'//引入maven插件}group'com.inkyi'//包名version'1.0.1-SNAPSHOT'//版本号1.2 build.gradle上传设置//指定上传的路径deflocalMavenRepo='file://'+new
Gradle的Emas服务插件会加载您下载的aliyun-emas-services.json文件。请修改工程的build.gradle使用该插件。配置步骤如下:1.修改项目级目录下build.gradle({project}/build.gradle):1buildscript{2repositories{3maven{4url'http://maven.aliyun.com