From eae0414cb494f4a8e37de0bced9b3eaaf71df132 Mon Sep 17 00:00:00 2001
From: huangzhuanghua <401742778@qq.com>
Date: Thu, 2 Mar 2017 10:28:41 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=A0=87=E7=AD=BE=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=EF=BC=8Ctinker=E6=8E=A5=E5=85=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle | 25 +-
app/src/main/AndroidManifest.xml | 6 +-
.../main/java/com/gh/base/AppController.java | 6 +
.../java/com/gh/base/AppControllerLike.java | 51 +++
.../com/gh/base/AppTinkerResultService.java | 29 ++
.../com/gh/common/util/GameViewUtils.java | 1 -
.../java/com/gh/gamecenter/MainActivity.java | 30 --
.../gh/gamecenter/MessageDetailActivity.java | 1 -
.../com/gh/gamecenter/SettingActivity.java | 13 -
.../download/GameDownloadFragmentAdapter.java | 2 -
.../gamedetail/GameDetailAdapter.java | 53 +--
.../gh/gamecenter/retrofit/ApiService.java | 3 -
app/src/main/res/layout/activity_setting.xml | 18 -
app/tinker-support.gradle | 323 ++++++++++++++++++
build.gradle | 1 +
gradle.properties | 4 +-
gradle/wrapper/gradle-wrapper.properties | 2 +-
17 files changed, 469 insertions(+), 99 deletions(-)
create mode 100644 app/src/main/java/com/gh/base/AppControllerLike.java
create mode 100644 app/src/main/java/com/gh/base/AppTinkerResultService.java
create mode 100644 app/tinker-support.gradle
diff --git a/app/build.gradle b/app/build.gradle
index 303bc4f8f4..4cd3a0f176 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,15 +4,18 @@ android {
compileSdkVersion 21
buildToolsVersion "23.0.3"
+ dexOptions {
+ jumboMode = true
+ }
+
defaultConfig {
applicationId "com.gh.gamecenter"
minSdkVersion 14
targetSdkVersion 21
- versionCode 18
- versionName "2.3"
+ versionCode 19
+ versionName "2.4"
- // 默认的渠道
-// manifestPlaceholders = [CHANNEL_VALUE: "GH_TEST"]
+ multiDexEnabled true
}
/**
@@ -39,6 +42,12 @@ android {
}
}
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ }
+ }
+
/**
* 多渠道打包
*/
@@ -129,4 +138,10 @@ dependencies {
// zxing 二维码扫描以及生成
compile 'com.google.zxing:core:3.2.1'
compile 'com.google.zxing:android-core:3.2.1'
-}
\ No newline at end of file
+ //tinker
+// compile("com.tencent.tinker:tinker-android-lib:${TINKER_VERSION}") { changing = true }
+// compile "com.android.support:multidex:1.0.1"
+}
+
+// 依赖插件脚本
+//apply from: 'tinker-support.gradle'
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 115da16725..cc54039eae 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -299,8 +299,12 @@
+
+
+
+
+ android:name="com.gh.gamecenter.statistics.AppStaticService" />
>(){
@@ -608,30 +607,38 @@ public class GameDetailAdapter extends RecyclerView.Adapter {
tv_content.setText(gameDetailEntity.getTips().getContent());
viewHolder.gamedetail_ll_plugin_colse.addView(view);
}
- for (int i = 0, size = tags.size(); i < size; i++) {
- view = View.inflate(context, R.layout.gamedetail_plugin_item, null);
- iv_hint = (SimpleDraweeView) view.findViewById(R.id.gamedetail_iv_hint);
- tv_hint = (TextView) view.findViewById(R.id.gamedetail_tv_hint);
- tv_content = (TextView) view.findViewById(R.id.gamedetail_tv_content);
- tagEntity = tags.get(i);
- tv_content.setText(tagEntity.getDes());
- tv_hint.setText(tagEntity.getName());
+
+ if (tags.isEmpty()) {
+ viewHolder.open_plugin_detail_ll.setVisibility(View.GONE);
+ } else {
+ viewHolder.open_plugin_detail_ll.setVisibility(View.VISIBLE);
+
+ for (int i = 0, size = tags.size(); i < size; i++) {
+ view = View.inflate(context, R.layout.gamedetail_plugin_item, null);
+ iv_hint = (SimpleDraweeView) view.findViewById(R.id.gamedetail_iv_hint);
+ tv_hint = (TextView) view.findViewById(R.id.gamedetail_tv_hint);
+ tv_content = (TextView) view.findViewById(R.id.gamedetail_tv_content);
+ tagEntity = tags.get(i);
+ tv_content.setText(tagEntity.getDes());
+ tv_hint.setText(tagEntity.getName());
// iv_hint.setImageURI(tagEntity.getIcon());
- ImageUtils.display(iv_hint, tagEntity.getIcon());
- viewHolder.gamedetail_ll_plugin.addView(view);
+ ImageUtils.display(iv_hint, tagEntity.getIcon());
+ viewHolder.gamedetail_ll_plugin.addView(view);
+ }
+
+ RecyclerView recyclerView = new RecyclerView(context);
+ recyclerView.setLayoutManager(new GridLayoutManager(context, 3));
+
+ int index = (int) Math.ceil(tags.size() / 3.0);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(context, index * 28));
+ params.setMargins(0, DisplayUtils.dip2px(context, index * 3), 0, 0);
+
+ recyclerView.setLayoutParams(params);
+ recyclerView.setAdapter(new PluginAdapter(tags));
+ viewHolder.gamedetail_ll_plugin_colse.addView(recyclerView);
}
- RecyclerView recyclerView = new RecyclerView(context);
- recyclerView.setLayoutManager(new GridLayoutManager(context, 3));
-
- int index = (int) Math.ceil(tags.size() / 3.0);
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(context, index * 28));
- params.setMargins(0, DisplayUtils.dip2px(context, index * 3), 0, 0);
-
- recyclerView.setLayoutParams(params);
- recyclerView.setAdapter(new PluginAdapter(tags));
- viewHolder.gamedetail_ll_plugin_colse.addView(recyclerView);
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/ApiService.java
index 22a3f4a032..c6d9bfbe41 100644
--- a/app/src/main/java/com/gh/gamecenter/retrofit/ApiService.java
+++ b/app/src/main/java/com/gh/gamecenter/retrofit/ApiService.java
@@ -78,9 +78,6 @@ public interface ApiService {
Observable getGameUpdate(@Path("gh_id") String gh_id,
@Path("package_name") String package_name);// 获取游戏更新
- @GET("disclaimer")
- Observable getDisclaimer(); // 获取免责声明
-
@GET("search/game/default")
Observable> getSearchHints(); // 获取搜索关键字
diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml
index dae50be70e..800f3b267d 100644
--- a/app/src/main/res/layout/activity_setting.xml
+++ b/app/src/main/res/layout/activity_setting.xml
@@ -348,24 +348,6 @@
android:textSize="12sp" />
-
-
-
-
diff --git a/app/tinker-support.gradle b/app/tinker-support.gradle
new file mode 100644
index 0000000000..d39f9c8f6a
--- /dev/null
+++ b/app/tinker-support.gradle
@@ -0,0 +1,323 @@
+def bakPath = file("${buildDir}/bakApk/")
+def bakName = "app-debug-0221-18-28-55"
+
+/**
+ * you can use assembleRelease to build you base apk
+ * use tinkerPatchRelease -POLD_APK= -PAPPLY_MAPPING= -PAPPLY_RESOURCE= to build patch
+ * add apk from the build/bakApk
+ */
+ext {
+ //for some reason, you may want to ignore tinkerBuild, such as instant run debug build?
+ tinkerEnabled = false
+
+ tinkerId = "base_${android.defaultConfig.versionName}"
+// tinkerId = "patch_${android.defaultConfig.versionName}"
+
+ //for normal build
+ //old apk file to build patch apk
+ tinkerOldApkPath = "${bakPath}/${bakName}.apk"
+ //proguard mapping file to build patch apk
+ tinkerApplyMappingPath = "${bakPath}/${bakName}-mapping.txt"
+ //resource R.txt to build patch apk, must input if there is resource changed
+ tinkerApplyResourcePath = "${bakPath}/${bakName}-R.txt"
+
+ //only use for build all flavor, if not, just ignore this field
+ tinkerBuildFlavorDirectory = "${bakPath}/app-0222-11-57-06"
+}
+
+def getOldApkPath() {
+ return hasProperty("OLD_APK") ? OLD_APK : ext.tinkerOldApkPath
+}
+
+def getApplyMappingPath() {
+ return hasProperty("APPLY_MAPPING") ? APPLY_MAPPING : ext.tinkerApplyMappingPath
+}
+
+def getApplyResourceMappingPath() {
+ return hasProperty("APPLY_RESOURCE") ? APPLY_RESOURCE : ext.tinkerApplyResourcePath
+}
+
+def getTinkerIdValue() {
+ return hasProperty("TINKER_ID") ? TINKER_ID : ext.tinkerId
+}
+
+def buildWithTinker() {
+ return hasProperty("TINKER_ENABLE") ? TINKER_ENABLE : ext.tinkerEnabled
+}
+
+def getTinkerBuildFlavorDirectory() {
+ return ext.tinkerBuildFlavorDirectory
+}
+
+if (buildWithTinker()) {
+ apply plugin: 'com.tencent.tinker.patch'
+
+ tinkerPatch {
+ /**
+ * necessary,default 'null'
+ * the old apk path, use to diff with the new apk to build
+ * add apk from the build/bakApk
+ */
+ oldApk = getOldApkPath()
+ /**
+ * optional,default 'false'
+ * there are some cases we may get some warnings
+ * if ignoreWarning is true, we would just assert the patch process
+ * case 1: minSdkVersion is below 14, but you are using dexMode with raw.
+ * it must be crash when load.
+ * case 2: newly added Android Component in AndroidManifest.xml,
+ * it must be crash when load.
+ * case 3: loader classes in dex.loader{} are not keep in the main dex,
+ * it must be let tinker not work.
+ * case 4: loader classes in dex.loader{} changes,
+ * loader classes is ues to load patch dex. it is useless to change them.
+ * it won't crash, but these changes can't effect. you may ignore it
+ * case 5: resources.arsc has changed, but we don't use applyResourceMapping to build
+ */
+ ignoreWarning = false
+
+ /**
+ * optional,default 'true'
+ * whether sign the patch file
+ * if not, you must do yourself. otherwise it can't check success during the patch loading
+ * we will use the sign config with your build type
+ */
+ useSign = true
+
+ /**
+ * optional,default 'true'
+ * whether use tinker to build
+ */
+ tinkerEnable = buildWithTinker()
+
+ /**
+ * Warning, applyMapping will affect the normal android build!
+ */
+ buildConfig {
+ /**
+ * optional,default 'null'
+ * if we use tinkerPatch to build the patch apk, you'd better to apply the old
+ * apk mapping file if minifyEnabled is enable!
+ * Warning:
+ * you must be careful that it will affect the normal assemble build!
+ */
+ applyMapping = getApplyMappingPath()
+ /**
+ * optional,default 'null'
+ * It is nice to keep the resource id from R.txt file to reduce java changes
+ */
+ applyResourceMapping = getApplyResourceMappingPath()
+
+ /**
+ * necessary,default 'null'
+ * because we don't want to check the base apk with md5 in the runtime(it is slow)
+ * tinkerId is use to identify the unique base apk when the patch is tried to apply.
+ * we can use git rev, svn rev or simply versionCode.
+ * we will gen the tinkerId in your manifest automatic
+ */
+ tinkerId = getTinkerIdValue()
+
+ /**
+ * if keepDexApply is true, class in which dex refer to the old apk.
+ * open this can reduce the dex diff file size.
+ */
+ keepDexApply = false
+ }
+
+ dex {
+ /**
+ * optional,default 'jar'
+ * only can be 'raw' or 'jar'. for raw, we would keep its original format
+ * for jar, we would repack dexes with zip format.
+ * if you want to support below 14, you must use jar
+ * or you want to save rom or check quicker, you can use raw mode also
+ */
+ dexMode = "jar"
+
+ /**
+ * necessary,default '[]'
+ * what dexes in apk are expected to deal with tinkerPatch
+ * it support * or ? pattern.
+ */
+ pattern = ["classes*.dex",
+ "assets/secondary-dex-?.jar"]
+ /**
+ * necessary,default '[]'
+ * Warning, it is very very important, loader classes can't change with patch.
+ * thus, they will be removed from patch dexes.
+ * you must put the following class into main dex.
+ * Simply, you should add your own application {@code tinker.sample.android.SampleApplication}
+ * own tinkerLoader, and the classes you use in them
+ *
+ */
+ loader = [
+ //use sample, let BaseBuildInfo unchangeable with tinker
+ "tinker.sample.android.app.BaseBuildInfo"
+ ]
+ }
+
+ lib {
+ /**
+ * optional,default '[]'
+ * what library in apk are expected to deal with tinkerPatch
+ * it support * or ? pattern.
+ * for library in assets, we would just recover them in the patch directory
+ * you can get them in TinkerLoadResult with Tinker
+ */
+ pattern = ["lib/*/*.so"]
+ }
+
+ res {
+ /**
+ * optional,default '[]'
+ * what resource in apk are expected to deal with tinkerPatch
+ * it support * or ? pattern.
+ * you must include all your resources in apk here,
+ * otherwise, they won't repack in the new apk resources.
+ */
+ pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
+
+ /**
+ * optional,default '[]'
+ * the resource file exclude patterns, ignore add, delete or modify resource change
+ * it support * or ? pattern.
+ * Warning, we can only use for files no relative with resources.arsc
+ */
+ ignoreChange = ["assets/sample_meta.txt"]
+
+ /**
+ * default 100kb
+ * for modify resource, if it is larger than 'largeModSize'
+ * we would like to use bsdiff algorithm to reduce patch file size
+ */
+ largeModSize = 100
+ }
+
+ packageConfig {
+ /**
+ * optional,default 'TINKER_ID, TINKER_ID_VALUE' 'NEW_TINKER_ID, NEW_TINKER_ID_VALUE'
+ * package meta file gen. path is assets/package_meta.txt in patch file
+ * you can use securityCheck.getPackageProperties() in your ownPackageCheck method
+ * or TinkerLoadResult.getPackageConfigByName
+ * we will get the TINKER_ID from the old apk manifest for you automatic,
+ * other config files (such as patchMessage below)is not necessary
+ */
+ configField("patchMessage", "tinker is sample to use")
+ /**
+ * just a sample case, you can use such as sdkVersion, brand, channel...
+ * you can parse it in the SamplePatchListener.
+ * Then you can use patch conditional!
+ */
+ configField("platform", "all")
+ /**
+ * patch version via packageConfig
+ */
+ configField("patchVersion", "1.0")
+ }
+ //or you can add config filed outside, or get meta value from old apk
+ //project.tinkerPatch.packageConfig.configField("test1", project.tinkerPatch.packageConfig.getMetaDataFromOldApk("Test"))
+ //project.tinkerPatch.packageConfig.configField("test2", "sample")
+
+ /**
+ * if you don't use zipArtifact or path, we just use 7za to try
+ */
+ sevenZip {
+ /**
+ * optional,default '7za'
+ * the 7zip artifact path, it will use the right 7za with your platform
+ */
+ zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
+ /**
+ * optional,default '7za'
+ * you can specify the 7za path yourself, it will overwrite the zipArtifact value
+ */
+// path = "/usr/local/bin/7za"
+ }
+ }
+
+ List flavors = new ArrayList<>();
+ project.android.productFlavors.each {flavor ->
+ flavors.add(flavor.name)
+ }
+ boolean hasFlavors = flavors.size() > 0
+ /**
+ * bak apk and mapping
+ */
+ android.applicationVariants.all { variant ->
+ /**
+ * task type, you want to bak
+ */
+ def taskName = variant.name
+ def date = new Date().format("MMdd-HH-mm-ss")
+
+ 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.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")
+ }
+ }
+ }
+ }
+ }
+ }
+ project.afterEvaluate {
+ //sample use for build all flavor for one time
+ if (hasFlavors) {
+ task(tinkerPatchAllFlavorRelease) {
+ group = 'tinker'
+ def originOldPath = getTinkerBuildFlavorDirectory()
+ for (String flavor : flavors) {
+ def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Release")
+ dependsOn tinkerTask
+ def preAssembleTask = tasks.getByName("process${flavor.capitalize()}ReleaseManifest")
+ preAssembleTask.doFirst {
+ String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 15)
+ project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release.apk"
+ project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-mapping.txt"
+ project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-R.txt"
+
+ }
+
+ }
+ }
+
+ task(tinkerPatchAllFlavorDebug) {
+ group = 'tinker'
+ def originOldPath = getTinkerBuildFlavorDirectory()
+ for (String flavor : flavors) {
+ def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Debug")
+ dependsOn tinkerTask
+ def preAssembleTask = tasks.getByName("process${flavor.capitalize()}DebugManifest")
+ preAssembleTask.doFirst {
+ String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 13)
+ project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug.apk"
+ project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-mapping.txt"
+ project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-R.txt"
+ }
+
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index be515a81ff..ff5371e15b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,6 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
+// classpath "com.tencent.tinker:tinker-patch-gradle-plugin:${TINKER_VERSION}"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle.properties b/gradle.properties
index 1d3591c8a4..70c772bb23 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -15,4 +15,6 @@
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
\ No newline at end of file
+# org.gradle.parallel=true
+
+TINKER_VERSION=1.7.7
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 536153e104..1e9bda3694 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Mon May 09 15:17:13 CST 2016
+#Wed Mar 01 17:16:39 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME