Skip to content

Commit 22cf41d

Browse files
committed
feat(main): commit sample
1 parent da18512 commit 22cf41d

29 files changed

+1058
-1
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea
5+
/.idea/libraries
6+
.DS_Store
7+
/build
8+
/captures
9+
buildSdk

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
# tinkerpatch-andresguard-sample
2-
A sample integrate AndResGuard
2+
3+
[ ![Download](https://api.bintray.com/packages/simsun/maven/tinkerpatch-android-sdk/images/download.svg) ](https://bintray.com/simsun/maven/tinkerpatch-android-sdk/_latestVersion)
4+
[![Join Slack](https://slack.tinkerpatch.com/badge.svg)](https://slack.tinkerpatch.com)
5+
6+
集成[AndResGuard](https://github.com/shwenzhang/AndResGuard)例子,可以直接copy 'andresguard.gradle'到您的项目中。
7+
8+
9+
[更多集成文档](http://tinkerpatch.com/Docs/intro)

app/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/build
2+
3+
/version.properties

app/andresguard.gradle

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
apply plugin: 'AndResGuard'
2+
3+
def bakPath = project.ext.TP_BAKPATH
4+
def baseInfo = project.ext.TP_BASEINFO
5+
def variantName = project.ext.TP_VARIANTNAME
6+
7+
8+
project.afterEvaluate {
9+
def date = new Date().format("MMdd-HH-mm-ss")
10+
def andResGuardApkSuffix = "andresguard.apk"
11+
12+
def apkSuffix = "_signed_7zip_aligned.apk"
13+
14+
/**
15+
* bak apk and mapping
16+
*/
17+
android.applicationVariants.all { variant ->
18+
/**
19+
* task type, you want to bak
20+
*/
21+
def taskName = variant.name
22+
String name = variant.name.toLowerCase()
23+
String destFilePrefix = "${project.name}-${name}"
24+
25+
// find resguard task first
26+
def resguardTask = project.tasks.findByName("resguard${taskName.capitalize()}")
27+
if (resguardTask == null) {
28+
println("resguardTask not found, just return")
29+
return
30+
}
31+
32+
def tinkerPatchTask = project.tasks.findByName("tinkerPatch${taskName.capitalize()}")
33+
if (tinkerPatchTask == null) {
34+
println("resguardTask not found, just return")
35+
return
36+
}
37+
38+
resguardTask.doFirst {
39+
def resMapping = "${bakPath}/${baseInfo}/${taskName}/${project.name}-${taskName}-resource_mapping.txt"
40+
File mapping = new File(resMapping)
41+
if (mapping.exists()) {
42+
println("change resguardTask mapping file to ${resMapping}")
43+
project.extensions.andResGuard.mappingFile = file(resMapping)
44+
}
45+
}
46+
tinkerPatchTask.doFirst {
47+
48+
def buildApkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}${apkSuffix}"
49+
if (!file(buildApkPath).exists()) {
50+
/** AndResGuard use the different suffix when apk using v2SignatureSchema **/
51+
apkSuffix = "_aligned_signed.apk"
52+
buildApkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}${apkSuffix}"
53+
}
54+
55+
println("change tinkerPatchTask buildApkPath to resugurad output ${buildApkPath}")
56+
tinkerPatchTask.buildApkPath = buildApkPath
57+
58+
println("change tinkerPatchTask baseApk to ${destFilePrefix}-${andResGuardApkSuffix}")
59+
project.extensions.tinkerPatch.oldApk = "${bakPath}/${baseInfo}/${variantName}/${destFilePrefix}-${andResGuardApkSuffix}"
60+
61+
}
62+
tinkerPatchTask.dependsOn resguardTask
63+
64+
resguardTask.doLast {
65+
String buildType = variant.buildType.name.toLowerCase()
66+
67+
if (!name.equalsIgnoreCase(buildType) && name.endsWith(buildType)) {
68+
name = name - buildType + "-${buildType}"
69+
}
70+
71+
String mAppVersion = project.extensions.tinkerpatchSupport.appVersion
72+
73+
String destPath = "${bakPath}/${project.name}-${mAppVersion}-${date}/${name}/"
74+
75+
copy {
76+
def apkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}${apkSuffix}"
77+
if (!file(apkPath).exists()) {
78+
/** AndResGuard use the different suffix when apk using v2SignatureSchema **/
79+
apkSuffix = "_aligned_signed.apk"
80+
apkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}${apkSuffix}"
81+
}
82+
from apkPath
83+
into file("${destPath}/")
84+
rename { String fileName ->
85+
fileName.replace("${project.getName()}-${taskName}${apkSuffix}", "${destFilePrefix}-${andResGuardApkSuffix}")
86+
}
87+
88+
from "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/resource_mapping_${project.getName()}-${taskName}.txt"
89+
into file("${destPath}/")
90+
rename { String fileName ->
91+
fileName.replace("resource_mapping_${project.getName()}-${taskName}.txt", "${destFilePrefix}-resource_mapping.txt")
92+
}
93+
}
94+
}
95+
}
96+
97+
}
98+
99+
100+
andResGuard {
101+
mappingFile = null
102+
use7zip = true
103+
useSign = true
104+
keepRoot = false
105+
// add <yourpackagename>.R.drawable.icon into whitelist.
106+
// because the launcher will get the icon with his name
107+
whiteList = [
108+
// your icon
109+
"R.drawable.icon",
110+
// for fabric
111+
"R.string.com.crashlytics.*",
112+
// for umeng update
113+
"R.string.umeng*",
114+
"R.string.UM*",
115+
"R.string.tb_*",
116+
"R.string.rc_*",
117+
"R.layout.umeng*",
118+
"R.layout.tb_*",
119+
"R.layout.rc_*",
120+
"R.drawable.umeng*",
121+
"R.drawable.tb_*",
122+
"R.drawable.rc_*",
123+
"R.drawable.u1*",
124+
"R.drawable.u2*",
125+
"R.anim.umeng*",
126+
"R.color.umeng*",
127+
"R.color.tb_*",
128+
"R.color.rc_*",
129+
"R.style.*UM*",
130+
"R.style.umeng*",
131+
"R.style.rc_*",
132+
"R.id.umeng*",
133+
"R.id.rc_*",
134+
// umeng share for sina
135+
"R.drawable.sina*",
136+
// for google-services.json
137+
"R.string.google_app_id",
138+
"R.string.gcm_defaultSenderId",
139+
"R.string.default_web_client_id",
140+
"R.string.ga_trackingId",
141+
"R.string.firebase_database_url",
142+
"R.string.google_api_key",
143+
"R.string.google_crash_reporting_api_key",
144+
"R.dimen.rc_*"
145+
]
146+
compressFilePattern = [
147+
"*.png",
148+
"*.jpg",
149+
"*.jpeg",
150+
"*.gif",
151+
"resources.arsc"
152+
]
153+
sevenzip {
154+
artifact = "com.tencent.mm:SevenZip:${ANDRESGUARD_VERSION}"
155+
//path = "/usr/local/bin/7za"
156+
}
157+
}

app/build.gradle

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
apply plugin: 'com.android.application'
2+
3+
dependencies {
4+
compile fileTree(dir: 'libs', include: ['*.jar'])
5+
compile "com.android.support:appcompat-v7:23.1.1"
6+
compile "com.android.support:multidex:1.0.1"
7+
8+
//无需引入tinker的任何库,使用tinkerpatch sdk即可
9+
compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") { changing = true }
10+
}
11+
12+
android {
13+
compileSdkVersion 23
14+
buildToolsVersion '25.0.2'
15+
16+
signingConfigs {
17+
debug {
18+
storeFile rootProject.file("keystore/debug.keystore")
19+
//v2SigningEnabled false
20+
}
21+
}
22+
23+
defaultConfig {
24+
applicationId "com.tinkerpatch.easy_sample"
25+
minSdkVersion 15
26+
targetSdkVersion 22
27+
versionCode 1
28+
versionName "1.0"
29+
multiDexEnabled true
30+
}
31+
32+
buildTypes {
33+
release {
34+
minifyEnabled true
35+
proguardFiles getDefaultProguardFile('proguard-android.txt')
36+
signingConfig signingConfigs.debug
37+
}
38+
debug {
39+
debuggable true
40+
minifyEnabled false
41+
signingConfig signingConfigs.debug
42+
}
43+
}
44+
45+
// productFlavors {
46+
// flavor1 {
47+
// applicationId 'com.tinkerpatch.easy_sample.flavor1'
48+
// }
49+
//
50+
// flavor2 {
51+
// applicationId 'com.tinkerpatch.easy_sample.flavor2'
52+
// }
53+
// }
54+
}
55+
56+
57+
apply from: 'tinkerpatch.gradle'

app/src/main/AndroidManifest.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest package="com.tinkerpatch.easy_sample"
3+
xmlns:android="http://schemas.android.com/apk/res/android">
4+
5+
<application
6+
android:name=".SampleApplication"
7+
android:allowBackup="true"
8+
android:icon="@mipmap/ic_launcher"
9+
android:label="@string/app_name"
10+
android:supportsRtl="true"
11+
android:theme="@style/AppTheme">
12+
<activity android:name=".MainActivity">
13+
<intent-filter>
14+
<action android:name="android.intent.action.MAIN"/>
15+
16+
<category android:name="android.intent.category.LAUNCHER"/>
17+
</intent-filter>
18+
</activity>
19+
</application>
20+
21+
</manifest>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.tinkerpatch.easy_sample;
2+
3+
import android.os.Handler;
4+
import android.os.Message;
5+
6+
import com.tinkerpatch.sdk.TinkerPatch;
7+
8+
/**
9+
* Created by zhangshaowen on 17/1/8.
10+
*/
11+
12+
public class FetchPatchHandler extends Handler {
13+
public static final long HOUR_INTERVAL = 3600 * 1000;
14+
15+
private long checkInterval;
16+
17+
/**
18+
* 通过handler, 达到按照时间间隔轮训的效果
19+
* @param hour
20+
*/
21+
public void fetchPatchWithInterval(int hour) {
22+
//设置TinkerPatch的时间间隔
23+
TinkerPatch.with().setFetchPatchIntervalByHours(hour);
24+
checkInterval = hour * HOUR_INTERVAL;
25+
//立刻尝试去访问,检查是否有更新
26+
sendEmptyMessage(0);
27+
}
28+
@Override
29+
public void handleMessage(Message msg) {
30+
super.handleMessage(msg);
31+
32+
//这里使用false即可
33+
TinkerPatch.with().fetchPatchUpdate(false);
34+
//每隔一段时间都去访问后台, 增加10分钟的buffer时间
35+
sendEmptyMessageDelayed(0, checkInterval + 10 * 60 * 1000);
36+
}
37+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.tinkerpatch.easy_sample;
2+
3+
import android.os.Bundle;
4+
import android.support.v7.app.AppCompatActivity;
5+
import android.util.Log;
6+
import android.view.View;
7+
import android.widget.Button;
8+
9+
import com.tencent.tinker.lib.util.TinkerLog;
10+
import com.tencent.tinker.loader.shareutil.ShareTinkerInternals;
11+
import com.tinkerpatch.sdk.TinkerPatch;
12+
import com.tinkerpatch.sdk.server.callback.ConfigRequestCallback;
13+
14+
import java.util.HashMap;
15+
16+
public class MainActivity extends AppCompatActivity {
17+
private static final String TAG = "Tinker.MainActivity";
18+
19+
@Override
20+
protected void onCreate(Bundle savedInstanceState) {
21+
super.onCreate(savedInstanceState);
22+
setContentView(R.layout.activity_main);
23+
Log.e(TAG, "I am on onCreate classloader1:" + MainActivity.class.getClassLoader().toString());
24+
//test resource change
25+
Log.e(TAG, "I am on onCreate string:" + getResources().getString(R.string.test_resource));
26+
// Log.e(TAG, "I am on patch onCreate");
27+
28+
Button requestPatchButton = (Button) findViewById(R.id.requestPatch);
29+
30+
//immediately 为 true, 每次强制访问服务器更新
31+
requestPatchButton.setOnClickListener(new View.OnClickListener() {
32+
@Override
33+
public void onClick(View v) {
34+
TinkerPatch.with().fetchPatchUpdate(true);
35+
}
36+
});
37+
38+
Button requestConfigButton = (Button) findViewById(R.id.requestConfig);
39+
40+
//immediately 为 true, 每次强制访问服务器更新
41+
requestConfigButton.setOnClickListener(new View.OnClickListener() {
42+
@Override
43+
public void onClick(View v) {
44+
TinkerPatch.with().fetchDynamicConfig(new ConfigRequestCallback() {
45+
46+
@Override
47+
public void onSuccess(HashMap<String, String> configs) {
48+
TinkerLog.w(TAG, "request config success, config:" + configs);
49+
}
50+
51+
@Override
52+
public void onFail(Exception e) {
53+
TinkerLog.w(TAG, "request config failed, exception:" + e);
54+
}
55+
}, true);
56+
}
57+
});
58+
59+
Button cleanPatchButton = (Button) findViewById(R.id.cleanPatch);
60+
61+
cleanPatchButton.setOnClickListener(new View.OnClickListener() {
62+
@Override
63+
public void onClick(View v) {
64+
TinkerPatch.with().cleanAll();
65+
}
66+
});
67+
68+
Button killSelfButton = (Button) findViewById(R.id.killSelf);
69+
70+
killSelfButton.setOnClickListener(new View.OnClickListener() {
71+
@Override
72+
public void onClick(View v) {
73+
ShareTinkerInternals.killAllOtherProcess(getApplicationContext());
74+
android.os.Process.killProcess(android.os.Process.myPid());
75+
}
76+
});
77+
}
78+
79+
@Override
80+
protected void onResume() {
81+
Log.e(TAG, "I am on onResume");
82+
super.onResume();
83+
84+
}
85+
86+
@Override
87+
protected void onPause() {
88+
Log.e(TAG, "I am on onPause");
89+
super.onPause();
90+
}
91+
}

0 commit comments

Comments
 (0)