1.导入依赖
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.9.2')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.9.2')
//分包
compile 'com.android.support:multidex:1.0.1'
----------------------------------------------------------------------------
1.1在AndroidManifast中配置:
<application>
<meta-data android:name="TINKER_ID" android:value="tinker_id_b168b32"/>
</application>
----------------------------------------------------------------------------
2.创建Application继承DefaultApplicationLike
public class CustomApplication extends DefaultApplicationLike{
public CustomApplication(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
//开启分包
MultiDex.install(base);
//安装
TinkerManager.installTinbker(this);
}
}
----------------------------------------------------------------------------
3.创建类TinkerManager
public class TinkerManager {
//是否安装
private static boolean isInstalled = false;
private static ApplicationLike app;
/**
* 安装
*/
public static void installTinbker(ApplicationLike applicationLike){
app=applicationLike;
//判断是否安装
if(isInstalled){
return;
}
TinkerInstaller.install(applicationLike);
isInstalled=true;
}
/**
* 添加补丁包
* @param path
*/
public static void addPatch(String path){
if(isInstalled){
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(),path);
}
}
/**
* 从ApplicationLike中拿到上下文
*/
public static Context getApplicationContext(){
return app.getApplication().getApplicationContext();
}
}
----------------------------------------------------------------------------
4.给Application类添加注解(第2步的类上添加此注解)
@DefaultLifeCycle(
application = ".MyTinkerApplication", //application name to generate 应用程序名称生成
flags = ShareConstants.TINKER_ENABLE_ALL) //tinkerFlags above tinkerFlags上面
4.1 编译一下生成一个.MyTinkerApplication 在清单文件中注册
----------------------------------------------------------------------------
5.在SD卡下生成一个文件夹 (路径名 /storage/emulated/0/tpatch/) //将生成的补丁包放入此文件夹下
//后缀
private static final String SUFFIX=".apk";
private String patchPath="";
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
patchPath=absolutePath.concat(File.separator).concat("tpatch/");
File file = new File(patchPath);
Log.e(TAG, "onCreate: 路径名 "+patchPath);
if(!file.exists()){
file.mkdir();
}
}
/**
* 返回补丁路径
* @return
*/
private String getPatchPath(){
return patchPath.concat("out").concat(SUFFIX);
}
点击调用方法: TinkerManager.addPatch(getPatchPath()); //添加补丁包
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
* gradle接入 *
1111111111111111111111111111111111111111111111111111111111111111111111111111111111
//在Project下build.gradle中配置
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.2')
}
//apply tinker插件 (在model的 build.gradle第二行配置)
apply plugin: 'com.tencent.tinker.patch'
----------------------------------------------------------------------------
22222222222222222222222222222222222222222222222222222222222222222222222222222222222
(在model的 build.gradle配置最下面)
在build下创建一个bakApk文件夹
def bakPath = file("${buildDir}/bakApk/")
ext{
tinkerOldApkPath = "${bakPath}/"
tinkerEnabled = true;
//不开启混淆
//tinkerApplyMappingPath = "${bakPath}/"
tinkerApplyResourcePath = "${bakPath}/"
//多渠道打包
//tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
def getOldApkPath() {
return ext.tinkerOldApkPath
}
//是否使用Tinker
def buildWithTinker() {
return ext.tinkerEnabled
}
def getApplyMappingPath() {
return ext.tinkerApplyMappingPath
}
def getApplyResourceMappingPath() {
return ext.tinkerApplyResourcePath
}
def getTinkerIdValue() {
return "tinker_id_b168b32"
}
//多渠道打包
/*def getTinkerBuildFlavorDirectory() {
return ext.tinkerBuildFlavorDirectory
}*/
tinkerPatch{
tinkerEnable = buildWithTinker()
oldApk = getOldApkPath()
ignoreWarning = false
useSign = true
buildConfig{
//不开启混淆不用他
//applyMapping = getApplyMappingPath()
applyResourceMapping = getApplyResourceMappingPath()
tinkerId = getTinkerIdValue()
keepDexApply = false //分包 暂时不用 太小
isProtectedApp = false //加固 暂时不加
}
dex{
dexMode = "jar"
pattern = ["classes*.dex",
"assets/secondary-dex-?.jar"]
//全路径Application
loader = ["com.geekghost.gp.tinker.MyTinkerApplication"]
}
lib{
pattern = ["lib/*/*.so"]
}
res{
pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
ignoreChange = ["assets/sample_meta.txt"]
largeModSize = 100
}
packageConfig{
configField ("version_name","1")
configField ("change_log","添加了一些新功能")
}
}
----------------------------------------------------------------------------
333333333333333333333333333333333333333333333333333333333333333333333333333
配置完成后打开右侧的Gradle,找到Tasks\build\assembleRelease双击编译一个Release的apk包
在项目的outputs\apk下
也可以在Terminal(命令行)输入 gradle assembleRelease 代替双击操作
----------------------------------------------------------------------------
444444444444444444444444444444444444444444444444444444444444444444444444444
此脚本在最下面复制 比较固定 用于生产老的apk文件
List<String> flavors = new ArrayList<>();
project.android.productFlavors.each { flavor ->
flavors.add(flavor.name)
}
boolean hasFlavors = flavors.size() > 0
def date = new Date().format("MMdd-HH-mm-ss")
/**
* bak apk and mapping
*/
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 fileNamePrefix = "${project.name}-${variant.baseName}"
def newFileNamePrefix = hasFlavors ? "${fileNamePrefix}" : "${fileNamePrefix}-${date}"
def destPath = hasFlavors ? file("${bakPath}/${project.name}-${date}/${variant.flavorName}") : bakPath
from variant.outputs.first().outputFile
into destPath
rename { String fileName ->
fileName.replace("${fileNamePrefix}.apk", "${newFileNamePrefix}.apk")
}
from "${buildDir}/outputs/mapping/${variant.dirName}/mapping.txt"
into destPath
rename { String fileName ->
fileName.replace("mapping.txt", "${newFileNamePrefix}-mapping.txt")
}
from "${buildDir}/intermediates/symbols/${variant.dirName}/R.txt"
into destPath
rename { String fileName ->
fileName.replace("R.txt", "${newFileNamePrefix}-R.txt")
}
}
}
}
}
}
----------------------------------------------------------------------------
55555555555555555555555555555555555555555555555555555555555555555555555555555
配置一个正式的签名文件 (可以快捷生产)
android {
signingConfigs {
release {
keyAlias 'key0'
keyPassword '123456'
storeFile file('C:/Users/ZangH/Desktop/Tinker/tk.jks')
storePassword '123456'
}
}
}
----------------------------------------------------------------------------
6666666666666666666666666666666666666666666666666666666666666666666666666666
重复3333333333333
这次生成后会在bakApk下生成一个备份的的apk和R文件
----------------------------------------------------------------------------
777777777777777777777777777777777777777777777777777777777777777777777777777
把bakApk的老的apk的名字copy下来把 tinkerOldApkPath = "${bakPath}/" 填好
把bakApk的老的R文件的名字copy下来把tinkerApplyResourcePath = "${bakPath}/" 填好
如下:
ext{
tinkerOldApkPath = "${bakPath}/tinker-release-0118-11-10-48.apk"
tinkerApplyResourcePath = "${bakPath}/tinker-release-0118-11-10-48-R.txt"
}
----------------------------------------------------------------------------
8888888888888888888888888888888888888888888888888888888888888888888888888888
上一步配置完成后点击打开右侧的Gradle,找到Tasks\tinker\tinkerPatchRelease双击编译一个新的包在
备份包里有新的R文件和apk,同时在build\output里的tinkerPatch里生成补丁apk(patch_signed.apk)
接下来只需把补丁包放入我们定义的修改路径就好了
然后每次更新补丁包生成新的apk后吧上一个备份好的apk和R文件路径修改即可:(具体看第7步)
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.9.2')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.9.2')
//分包
compile 'com.android.support:multidex:1.0.1'
----------------------------------------------------------------------------
1.1在AndroidManifast中配置:
<application>
<meta-data android:name="TINKER_ID" android:value="tinker_id_b168b32"/>
</application>
----------------------------------------------------------------------------
2.创建Application继承DefaultApplicationLike
public class CustomApplication extends DefaultApplicationLike{
public CustomApplication(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
//开启分包
MultiDex.install(base);
//安装
TinkerManager.installTinbker(this);
}
}
----------------------------------------------------------------------------
3.创建类TinkerManager
public class TinkerManager {
//是否安装
private static boolean isInstalled = false;
private static ApplicationLike app;
/**
* 安装
*/
public static void installTinbker(ApplicationLike applicationLike){
app=applicationLike;
//判断是否安装
if(isInstalled){
return;
}
TinkerInstaller.install(applicationLike);
isInstalled=true;
}
/**
* 添加补丁包
* @param path
*/
public static void addPatch(String path){
if(isInstalled){
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(),path);
}
}
/**
* 从ApplicationLike中拿到上下文
*/
public static Context getApplicationContext(){
return app.getApplication().getApplicationContext();
}
}
----------------------------------------------------------------------------
4.给Application类添加注解(第2步的类上添加此注解)
@DefaultLifeCycle(
application = ".MyTinkerApplication", //application name to generate 应用程序名称生成
flags = ShareConstants.TINKER_ENABLE_ALL) //tinkerFlags above tinkerFlags上面
4.1 编译一下生成一个.MyTinkerApplication 在清单文件中注册
----------------------------------------------------------------------------
5.在SD卡下生成一个文件夹 (路径名 /storage/emulated/0/tpatch/) //将生成的补丁包放入此文件夹下
//后缀
private static final String SUFFIX=".apk";
private String patchPath="";
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
patchPath=absolutePath.concat(File.separator).concat("tpatch/");
File file = new File(patchPath);
Log.e(TAG, "onCreate: 路径名 "+patchPath);
if(!file.exists()){
file.mkdir();
}
}
/**
* 返回补丁路径
* @return
*/
private String getPatchPath(){
return patchPath.concat("out").concat(SUFFIX);
}
点击调用方法: TinkerManager.addPatch(getPatchPath()); //添加补丁包
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
* gradle接入 *
1111111111111111111111111111111111111111111111111111111111111111111111111111111111
//在Project下build.gradle中配置
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.2')
}
//apply tinker插件 (在model的 build.gradle第二行配置)
apply plugin: 'com.tencent.tinker.patch'
----------------------------------------------------------------------------
22222222222222222222222222222222222222222222222222222222222222222222222222222222222
(在model的 build.gradle配置最下面)
在build下创建一个bakApk文件夹
def bakPath = file("${buildDir}/bakApk/")
ext{
tinkerOldApkPath = "${bakPath}/"
tinkerEnabled = true;
//不开启混淆
//tinkerApplyMappingPath = "${bakPath}/"
tinkerApplyResourcePath = "${bakPath}/"
//多渠道打包
//tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
def getOldApkPath() {
return ext.tinkerOldApkPath
}
//是否使用Tinker
def buildWithTinker() {
return ext.tinkerEnabled
}
def getApplyMappingPath() {
return ext.tinkerApplyMappingPath
}
def getApplyResourceMappingPath() {
return ext.tinkerApplyResourcePath
}
def getTinkerIdValue() {
return "tinker_id_b168b32"
}
//多渠道打包
/*def getTinkerBuildFlavorDirectory() {
return ext.tinkerBuildFlavorDirectory
}*/
tinkerPatch{
tinkerEnable = buildWithTinker()
oldApk = getOldApkPath()
ignoreWarning = false
useSign = true
buildConfig{
//不开启混淆不用他
//applyMapping = getApplyMappingPath()
applyResourceMapping = getApplyResourceMappingPath()
tinkerId = getTinkerIdValue()
keepDexApply = false //分包 暂时不用 太小
isProtectedApp = false //加固 暂时不加
}
dex{
dexMode = "jar"
pattern = ["classes*.dex",
"assets/secondary-dex-?.jar"]
//全路径Application
loader = ["com.geekghost.gp.tinker.MyTinkerApplication"]
}
lib{
pattern = ["lib/*/*.so"]
}
res{
pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
ignoreChange = ["assets/sample_meta.txt"]
largeModSize = 100
}
packageConfig{
configField ("version_name","1")
configField ("change_log","添加了一些新功能")
}
}
----------------------------------------------------------------------------
333333333333333333333333333333333333333333333333333333333333333333333333333
配置完成后打开右侧的Gradle,找到Tasks\build\assembleRelease双击编译一个Release的apk包
在项目的outputs\apk下
也可以在Terminal(命令行)输入 gradle assembleRelease 代替双击操作
----------------------------------------------------------------------------
444444444444444444444444444444444444444444444444444444444444444444444444444
此脚本在最下面复制 比较固定 用于生产老的apk文件
List<String> flavors = new ArrayList<>();
project.android.productFlavors.each { flavor ->
flavors.add(flavor.name)
}
boolean hasFlavors = flavors.size() > 0
def date = new Date().format("MMdd-HH-mm-ss")
/**
* bak apk and mapping
*/
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 fileNamePrefix = "${project.name}-${variant.baseName}"
def newFileNamePrefix = hasFlavors ? "${fileNamePrefix}" : "${fileNamePrefix}-${date}"
def destPath = hasFlavors ? file("${bakPath}/${project.name}-${date}/${variant.flavorName}") : bakPath
from variant.outputs.first().outputFile
into destPath
rename { String fileName ->
fileName.replace("${fileNamePrefix}.apk", "${newFileNamePrefix}.apk")
}
from "${buildDir}/outputs/mapping/${variant.dirName}/mapping.txt"
into destPath
rename { String fileName ->
fileName.replace("mapping.txt", "${newFileNamePrefix}-mapping.txt")
}
from "${buildDir}/intermediates/symbols/${variant.dirName}/R.txt"
into destPath
rename { String fileName ->
fileName.replace("R.txt", "${newFileNamePrefix}-R.txt")
}
}
}
}
}
}
----------------------------------------------------------------------------
55555555555555555555555555555555555555555555555555555555555555555555555555555
配置一个正式的签名文件 (可以快捷生产)
android {
signingConfigs {
release {
keyAlias 'key0'
keyPassword '123456'
storeFile file('C:/Users/ZangH/Desktop/Tinker/tk.jks')
storePassword '123456'
}
}
}
----------------------------------------------------------------------------
6666666666666666666666666666666666666666666666666666666666666666666666666666
重复3333333333333
这次生成后会在bakApk下生成一个备份的的apk和R文件
----------------------------------------------------------------------------
777777777777777777777777777777777777777777777777777777777777777777777777777
把bakApk的老的apk的名字copy下来把 tinkerOldApkPath = "${bakPath}/" 填好
把bakApk的老的R文件的名字copy下来把tinkerApplyResourcePath = "${bakPath}/" 填好
如下:
ext{
tinkerOldApkPath = "${bakPath}/tinker-release-0118-11-10-48.apk"
tinkerApplyResourcePath = "${bakPath}/tinker-release-0118-11-10-48-R.txt"
}
----------------------------------------------------------------------------
8888888888888888888888888888888888888888888888888888888888888888888888888888
上一步配置完成后点击打开右侧的Gradle,找到Tasks\tinker\tinkerPatchRelease双击编译一个新的包在
备份包里有新的R文件和apk,同时在build\output里的tinkerPatch里生成补丁apk(patch_signed.apk)
接下来只需把补丁包放入我们定义的修改路径就好了
然后每次更新补丁包生成新的apk后吧上一个备份好的apk和R文件路径修改即可:(具体看第7步)