├── .gitignore ├── README.md ├── app ├── .gitignore ├── and_res_guard.gradle ├── build.gradle ├── demo.jks ├── proguard-rules.pro ├── src │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── chaychan │ │ │ └── tinkerandresguarddemo │ │ │ └── ExampleInstrumentedTest.java │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── chaychan │ │ │ │ └── tinkerandresguarddemo │ │ │ │ ├── BugClass.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MyApplication.java │ │ │ │ └── MyApplicationLike.java │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ └── test │ │ └── java │ │ └── com │ │ └── chaychan │ │ └── tinkerandresguarddemo │ │ └── ExampleUnitTest.java └── tinker-support.gradle ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── version.properties /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 该项目为结合Tinker热更新与AndResGuard资源混淆的DEMO 2 | 3 | ### Blog 4 | 5 | 详细介绍和使用可以查看我的博客: 6 | 7 | [http://blog.csdn.net/chay_chan/article/details/79106711](http://blog.csdn.net/chay_chan/article/details/79106711) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/and_res_guard.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'AndResGuard' 2 | 3 | def bakPath = bakPath() 4 | 5 | /** 6 | * 此处填写每次构建生成的基准包目录 7 | */ 8 | def baseApkDir = baseApkDir() 9 | 10 | andResGuard { 11 | mappingFile = null 12 | // mappingFile = file("${bakPath}/${baseApkDir}/${appName()}-resource_mapping.txt") 13 | use7zip = true 14 | useSign = true 15 | keepRoot = false 16 | compressFilePattern = [ 17 | "*.png", 18 | "*.jpg", 19 | "*.jpeg", 20 | "*.gif", 21 | "resources.arsc" 22 | ] 23 | whiteList = [ 24 | // your icon 25 | "R.drawable.icon", 26 | // for fabric 27 | "R.string.com.crashlytics.*", 28 | // for umeng update 29 | "R.string.tb_*", 30 | "R.layout.tb_*", 31 | "R.drawable.tb_*", 32 | "R.drawable.u1*", 33 | "R.drawable.u2*", 34 | "R.color.tb_*", 35 | // umeng share for sina 36 | "R.drawable.sina*", 37 | // for google-services.json 38 | "R.string.google_app_id", 39 | "R.string.gcm_defaultSenderId", 40 | "R.string.default_web_client_id", 41 | "R.string.ga_trackingId", 42 | "R.string.firebase_database_url", 43 | "R.string.google_api_key", 44 | "R.string.google_crash_reporting_api_key", 45 | 46 | //友盟 47 | "R.string.umeng*", 48 | "R.string.UM*", 49 | "R.layout.umeng*", 50 | "R.drawable.umeng*", 51 | "R.id.umeng*", 52 | "R.anim.umeng*", 53 | "R.color.umeng*", 54 | "R.style.*UM*", 55 | "R.style.umeng*", 56 | 57 | //融云 58 | "R.drawable.u*", 59 | "R.drawable.rc_*", 60 | "R.string.rc_*", 61 | "R.layout.rc_*", 62 | "R.color.rc_*", 63 | "R.id.rc_*", 64 | "R.style.rc_*", 65 | "R.dimen.rc_*", 66 | "R.array.rc_*" 67 | ] 68 | 69 | sevenzip { 70 | artifact = 'com.tencent.mm:SevenZip:1.2.10' 71 | //path = "/usr/local/bin/7za" 72 | } 73 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply from: 'and_res_guard.gradle' 3 | apply from: 'tinker-support.gradle' 4 | 5 | def bakPath(){ 6 | return file("${buildDir}/bakApk/") 7 | } 8 | 9 | /** 10 | * 此处填写每次构建生成的基准包目录 11 | */ 12 | def baseApkDir(){ 13 | return "resguard-0119-10-52-28" 14 | } 15 | 16 | def detailedBuildTime() { 17 | return new Date().format("MMdd-HH-mm-ss", TimeZone.getTimeZone("GMT+8")) 18 | } 19 | 20 | def appName(){ 21 | return "${project.getName()}" 22 | } 23 | 24 | //获取版本号 25 | def verCode() { 26 | def versionPropsFile = file("../version.properties") 27 | if (versionPropsFile.canRead()) { 28 | Properties versionProps = new Properties() 29 | versionProps.load(new FileInputStream(versionPropsFile)) 30 | 31 | def int verCode = versionProps['VERSION_CODE'].toInteger() 32 | return verCode; 33 | } else { 34 | throw new GradleException("Could not read gradle.properties") 35 | } 36 | } 37 | 38 | //获取版本名 39 | def verName() { 40 | def versionPropsFile = file("../version.properties") 41 | if (versionPropsFile.canRead()) { 42 | Properties versionProps = new Properties() 43 | versionProps.load(new FileInputStream(versionPropsFile)) 44 | 45 | return versionProps['VERSION_NAME'] 46 | } else { 47 | throw new GradleException("Could not read gradle.properties") 48 | } 49 | } 50 | 51 | android { 52 | compileSdkVersion 26 53 | defaultConfig { 54 | applicationId "com.chaychan.tinkerandresguarddemo" 55 | minSdkVersion 16 56 | targetSdkVersion 26 57 | versionCode verCode() 58 | versionName verName() 59 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 60 | multiDexEnabled true 61 | } 62 | 63 | //recommend 64 | dexOptions { 65 | jumboMode = true 66 | } 67 | 68 | 69 | signingConfigs { 70 | demo { 71 | keyAlias KEY_ALIAS 72 | keyPassword KEY_PASSWORD 73 | storeFile file(KEY_FILE_PATH) 74 | storePassword KEY_STORE_PASSWORD 75 | } 76 | } 77 | 78 | buildTypes { 79 | debug { 80 | minifyEnabled true 81 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 82 | signingConfig signingConfigs.demo 83 | } 84 | release { 85 | minifyEnabled true 86 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 87 | signingConfig signingConfigs.demo 88 | } 89 | } 90 | 91 | /** 92 | * bak apk and mapping 93 | */ 94 | android.applicationVariants.all { variant -> 95 | /** 96 | * task type, you want to bak 97 | */ 98 | def taskName = variant.name 99 | 100 | 101 | tasks.all { 102 | 103 | if (variant.buildType.name == 'release') { 104 | 105 | def andResDir = "${buildDir}/outputs/apk/${taskName}/AndResGuard_${project.getName()}-${taskName}"; 106 | 107 | if ("tinkerPatch${taskName.capitalize()}".equalsIgnoreCase(it.name)) { 108 | 109 | // find resguard task 110 | def resguardTask 111 | tasks.all { 112 | if (it.name.startsWith("resguard${taskName.capitalize()}")) { 113 | resguardTask = it 114 | } 115 | } 116 | it.doFirst({ 117 | // change build apk path 118 | it.buildApkPath = "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk" 119 | }) 120 | 121 | // change task dependence to resguard task 122 | it.dependsOn resguardTask 123 | 124 | } 125 | 126 | if ("resguard${taskName.capitalize()}".equalsIgnoreCase(it.name)) { 127 | it.doLast { 128 | copy { 129 | def outDir = file("${bakPath()}/resguard-${detailedBuildTime()}") 130 | 131 | from "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk" 132 | into outDir 133 | rename { String fileName -> 134 | fileName.replace("${project.getName()}-${taskName}_aligned_signed.apk", "${appName()}.apk") 135 | } 136 | 137 | from "${buildDir}/outputs/mapping/${taskName}/mapping.txt" 138 | into outDir 139 | rename { String fileName -> 140 | fileName.replace("mapping.txt", "${appName()}-mapping.txt") 141 | } 142 | 143 | from "${buildDir}/intermediates/symbols/${taskName}/R.txt" 144 | into outDir 145 | rename { String fileName -> 146 | fileName.replace("R.txt", "${appName()}-R.txt") 147 | } 148 | 149 | from "${andResDir}/resource_mapping_${project.getName()}-release.txt" 150 | into outDir 151 | rename { String fileName -> 152 | fileName.replace("resource_mapping_${project.getName()}-release.txt", "${appName()}-resource_mapping.txt") 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } 159 | } 160 | } 161 | 162 | dependencies { 163 | implementation fileTree(dir: 'libs', include: ['*.jar']) 164 | implementation 'com.android.support:appcompat-v7:26.1.0' 165 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 166 | testImplementation 'junit:junit:4.12' 167 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 168 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 169 | compile 'com.tencent.bugly:crashreport_upgrade:1.3.2' 170 | } 171 | -------------------------------------------------------------------------------- /app/demo.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaychan/TinkerAndResGuardDemo/d480a81e436eb941c7aae389810836dadf499267/app/demo.jks -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/chaychan/tinkerandresguarddemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.tinkerandresguarddemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.chaychan.tinkerandresguarddemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/tinkerandresguarddemo/BugClass.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.tinkerandresguarddemo; 2 | 3 | /** 4 | * @author ChayChan 5 | * @description: TODO 6 | * @date 2018/1/18 19:37 7 | */ 8 | 9 | 10 | public class BugClass { 11 | 12 | public static String getString(){ 13 | String str = "Bug has Fixed!"; 14 | int length = str.length(); 15 | return str; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/tinkerandresguarddemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.tinkerandresguarddemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | } 15 | 16 | public void show(View view){ 17 | Toast.makeText(this,BugClass.getString(), Toast.LENGTH_SHORT).show(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/tinkerandresguarddemo/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.tinkerandresguarddemo; 2 | 3 | import com.tencent.tinker.loader.app.TinkerApplication; 4 | import com.tencent.tinker.loader.shareutil.ShareConstants; 5 | 6 | /** 7 | * @author ChayChan 8 | * @description: TODO 9 | * @date 2017/11/17 21:36 10 | */ 11 | 12 | public class MyApplication extends TinkerApplication { 13 | 14 | public MyApplication() { 15 | super(ShareConstants.TINKER_ENABLE_ALL, MyApplicationLike.class.getCanonicalName(), 16 | "com.tencent.tinker.loader.TinkerLoader", false); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/tinkerandresguarddemo/MyApplicationLike.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.tinkerandresguarddemo; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Build; 8 | import android.support.multidex.MultiDex; 9 | 10 | import com.tencent.bugly.Bugly; 11 | import com.tencent.bugly.beta.Beta; 12 | import com.tencent.tinker.loader.app.DefaultApplicationLike; 13 | 14 | /** 15 | * @author ChayChan 16 | * @description: TODO 17 | * @date 2017/11/17 21:41 18 | */ 19 | 20 | public class MyApplicationLike extends DefaultApplicationLike { 21 | 22 | public MyApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) { 23 | super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent); 24 | } 25 | 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId 30 | // 调试时,将第三个参数改为true 31 | Bugly.init(getApplication(), "5d892615cf", true); 32 | } 33 | 34 | 35 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 36 | @Override 37 | public void onBaseContextAttached(Context base) { 38 | super.onBaseContextAttached(base); 39 | // you must install multiDex whatever tinker is installed! 40 | MultiDex.install(base); 41 | 42 | // 安装tinker 43 | // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法 44 | Beta.installTinker(this); 45 | } 46 | 47 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 48 | public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) { 49 | getApplication().registerActivityLifecycleCallbacks(callbacks); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 172 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |