Android 热修复 Tinker接入
2017-03-31 11:09
567 查看
转自:http://www.jianshu.com/p/9680a58e67fe
Demo地址
官方Demo
Tinker官方Wiki
新建项目,添加gradle依赖在项目的 build.gradle 中,添加tinker-patch-gradle-plugin的依赖
在app的gradle文件,我们需要添加tinker的库依赖以及apply tinker的gradle插件.
顺便加一下签名的配置,放在项目目录。
签名文件的位置.png
此时构建项目也许会遇到下面问题
Paste_Image.png
在下面的build.gradle 中设置tinker 配置,具体请看下一段代码。
Paste_Image.png
对tinker 进行配置,整个build.gradle文件如下所示。直接拷贝自己需要的就行。
添加(或修改)项目的 Application ,使之继承DefaultApplicationLike。
然后修改manifest.xml将application指向com.youxiake.tinkerdemo.SampleApplication就行,开始会报错,build一下项目就好了
Paste_Image.png
!!!指定 application 有三个注意的地方 ,如下这三个地方的application应该是一致的
Paste_Image.png
gradle的application.png
清单文件的application.png
这个案例中我们会将patch文件直接push到sdcard根目录,要从sdcard中读取补丁,所以要添加权限。
一定要注意:添加SDCard权限,如果你是6.x以上的系统,自己添加上授权代码(6.0权限问题),或者手动在手机设置页面打开SDCard读写权限。
搭建完成,开始进行测试了,在activity中新建如下代码。
先运行一个 应用出错的程序在手机上作为上线出bug的版本,运行图中的assembleDebug ,会在图一中生成debug文件。根据出错的apk的日期,去设置build.gredle 中 出错包的信息
Paste_Image.png
Paste_Image.png
运行tinkerPatchDebug,开始生成补丁
运行tinkerPatchDebug.png
(手机root过或者模拟器)通过adb push 补丁到和MainActivity中加载补丁的路径一致,补丁重命名 patch(随便在下怎么取名,一致就行)
TinkerInstaller.onReceiveUpgradePatch(this, Environment.getExternalStorageDirectory().getAbsolutePath()+"/patch");
adb push.png
result.png
Demo地址
官方Demo
Tinker官方Wiki
新建项目,添加gradle依赖在项目的 build.gradle 中,添加tinker-patch-gradle-plugin的依赖
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.0' classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7') // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }allprojects { repositories { jcenter() } }task clean(type: Delete) { delete rootProject.buildDir }
在app的gradle文件,我们需要添加tinker的库依赖以及apply tinker的gradle插件.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile "com.android.support:appcompat-v7:23.1.1" compile("com.tencent.tinker:tinker-android-lib:1.7.7") { changing = true } provided("com.tencent.tinker:tinker-android-anno:1.7.7") { changing = true } compile "com.android.support:multidex:1.0.1" } //apply tinker插件 apply plugin: 'com.tencent.tinker.patch'
顺便加一下签名的配置,放在项目目录。
签名文件的位置.png
此时构建项目也许会遇到下面问题
Paste_Image.png
在下面的build.gradle 中设置tinker 配置,具体请看下一段代码。
Paste_Image.png
对tinker 进行配置,整个build.gradle文件如下所示。直接拷贝自己需要的就行。
apply plugin: 'com.android.application' //apply tinker插件 apply plugin: 'com.tencent.tinker.patch' android { compileSdkVersion 25 buildToolsVersion "25.0.1" defaultConfig { applicationId "com.youxiake.tinkerdemo" minSdkVersion 14 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } signingConfigs { release { try { storeFile file("release.jks") storePassword "testres" keyAlias "testres" keyPassword "testres" } catch (ex) { throw new InvalidUserDataException(ex.toString()) } } } buildTypes { release { minifyEnabled true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { debuggable true minifyEnabled true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.1' testCompile 'junit:junit:4.12' //可选,用于生成application类 provided('com.tencent.tinker:tinker-android-anno:1.7.7') //tinker的核心库 compile('com.tencent.tinker:tinker-android-lib:1.7.7') compile "com.android.support:multidex:1.0.1" } def bakPath = file("${buildDir}/bakApk/") ext { tinkerEnabled = true tinkerOldApkPath = "${bakPath}/app-debug-0209-10-09-21.apk" //proguard mapping file to build patch apk tinkerApplyMappingPath = "${bakPath}/" //resource R.txt to build patch apk, must input if there is resource changed tinkerApplyResourcePath = "${bakPath}/app-debug-0209-10-09-21-R.txt" } def getOldApkPath() { return ext.tinkerOldApkPath } def getApplyMappingPath() { return ext.tinkerApplyMappingPath } def getApplyResourceMappingPath() { return ext.tinkerApplyResourcePath } if (ext.tinkerEnabled) { tinkerPatch { oldApk = getOldApkPath() ignoreWarning = false useSign = true // packageConfig { // // configField("TINKER_ID", "2.0") // } buildConfig{ tinkerId = "1.0" applyMapping = getApplyMappingPath() applyResourceMapping = getApplyResourceMappingPath() } lib { pattern = ["lib/armeabi/*.so"] } res { pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"] ignoreChange = ["assetsmple_meta.txt"] largeModSize = 100 } sevenZip { zipArtifact = "com.tencent.mm:SevenZip:1.1.10" } dex { dexMode = "jar" pattern = ["classes*.dex", "assetscondary-dex-?.jar"] loader = ["com.tencent.tinker.loader.*", "com.tencent.tinker.*", "com.youxiake.tinkerdemo.SampleApplication" ] } } } android.applicationVariants.all { variant -> /** * task type, you want to bak */ def taskName = variant.name tasks.all { if ("assemble${taskName.capitalize()}".equalsIgnoreCase(it.name)) { it.doLast { copy { def date = new Date().format("MMdd-HH-mm-ss") from "${buildDir}/outputs/apk/${project.getName()}-${taskName}.apk" into bakPath rename { String fileName -> fileName.replace("${project.getName()}-${taskName}.apk", "${project.getName()}-${taskName}-${date}.apk") } from "${buildDir}/outputs/mapping/${taskName}/mapping.txt" into bakPath rename { String fileName -> fileName.replace("mapping.txt", "${project.getName()}-${taskName}-${date}-mapping.txt") } from "${buildDir}/intermediates/symbols/${taskName}/R.txt" into bakPath rename { String fileName -> fileName.replace("R.txt", "${project.getName()}-${taskName}-${date}-R.txt") } } } } } }
添加(或修改)项目的 Application ,使之继承DefaultApplicationLike。
@SuppressWarnings("unused") @DefaultLifeCycle(application = "com.youxiake.tinkerdemo.SampleApplication", flags = ShareConstants.TINKER_ENABLE_ALL, loadVerifyFlag = false) public class SampleApplicationLike extends DefaultApplicationLike { private static final String TAG = "Tinker.SampleApplicationLike"; public SampleApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) { super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent); } /** * install multiDex before install tinker * so we don't need to put the tinker lib classes in the main dex * * @param base */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onBaseContextAttached(Context base) { super.onBaseContextAttached(base); //you must install multiDex whatever tinker is installed! MultiDex.install(base); //installTinker after load multiDex //or you can put com.tencent.tinker.** to main dex TinkerInstaller.install(this); } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) { getApplication().registerActivityLifecycleCallbacks(callback); } }
然后修改manifest.xml将application指向com.youxiake.tinkerdemo.SampleApplication就行,开始会报错,build一下项目就好了
Paste_Image.png
!!!指定 application 有三个注意的地方 ,如下这三个地方的application应该是一致的
Paste_Image.png
gradle的application.png
清单文件的application.png
这个案例中我们会将patch文件直接push到sdcard根目录,要从sdcard中读取补丁,所以要添加权限。
一定要注意:添加SDCard权限,如果你是6.x以上的系统,自己添加上授权代码(6.0权限问题),或者手动在手机设置页面打开SDCard读写权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
搭建完成,开始进行测试了,在activity中新建如下代码。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(this,"应用出错了....",Toast.LENGTH_SHORT).show(); //进行补丁的操作 TinkerInstaller.onReceiveUpgradePatch(this, Environment.getExternalStorageDirectory().getAbsolutePath()+"/patch"); } }
先运行一个 应用出错的程序在手机上作为上线出bug的版本,运行图中的assembleDebug ,会在图一中生成debug文件。根据出错的apk的日期,去设置build.gredle 中 出错包的信息
Paste_Image.png
Paste_Image.png
将MainActivity中的 Toast 修改。(代表修改好的包)
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(this,"应用正常了....",Toast.LENGTH_SHORT).show(); //进行补丁的操作 TinkerInstaller.onReceiveUpgradePatch(this, Environment.getExternalStorageDirectory().getAbsolutePath()+"/patch"); } }
运行tinkerPatchDebug,开始生成补丁
运行tinkerPatchDebug.png
(手机root过或者模拟器)通过adb push 补丁到和MainActivity中加载补丁的路径一致,补丁重命名 patch(随便在下怎么取名,一致就行)
TinkerInstaller.onReceiveUpgradePatch(this, Environment.getExternalStorageDirectory().getAbsolutePath()+"/patch");
adb push.png
最后结果 (第一次写,太唠叨了)
Demo地址github
result.png
相关文章推荐
- Android 热修复 Tinker接入及源码浅析
- Android 热修复 Tinker接入及源码浅析
- Android 热修复 Tinker接入及源码浅析
- Android 热修复 Tinker接入及源码浅析
- Android热修复Tinker接入及源码解读
- Android 热修复Tinker接入实战
- Android热修复之Tinker接入流程
- Android 微信Tinker三分钟接入七分钟原理 让你成为热修复牛人
- Android 热修复 Tinker接入及源码浅析
- 初探Android热修复——tinker接入
- Android 热修复 关于接入Tinker所遇到的错误
- Android 热修复 Tinker 接入
- Android热修复框架Tinker接入
- Android热修复框架 Tinker 接入
- Android 热修复 Tinker接入及源码浅析最精彩没有之一
- Android 微信热修复 Tinker 接入过程及使用方法
- Android 笔记 :Android 热修复 Tinker接入及源码浅析
- android 微信热修复Tinker接入过程以及使用方法
- Android 热修复,微信开源框架tinker的接入,就是这么简单
- Android 热修复 Tinker接入方法