From b950fae5092aa4daca355eb12578c98d4ad800fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AD=E5=BB=BA=E5=B8=85?= Date: Thu, 27 Sep 2018 10:21:22 +0800 Subject: [PATCH] update --- LICENSE | 202 ++++++++++ README.md | 207 +++++++--- {sample/app => app}/.gitignore | 0 app/build.gradle | 111 ++++++ app/channel | 28 ++ app/channel_debug | 2 + app/config.json | 68 ++++ .../keystore/sign-debug.keystore | Bin {sample/app => app}/proguard-rules.pro | 0 .../app => app}/src/main/AndroidManifest.xml | 0 .../android/walle/sample/MainActivity.java | 37 ++ .../android/walle/sample/MyApplication.java | 0 .../src/main/res/layout/activity_main.xml | 9 +- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../src/main/res/values-w820dp/dimens.xml | 0 .../src/main/res/values/colors.xml | 0 .../src/main/res/values/dimens.xml | 0 .../src/main/res/values/strings.xml | 0 .../src/main/res/values/styles.xml | 0 assets/walle.png | Bin 323528 -> 0 bytes build.gradle | 27 +- config/style/checkstyle.xml | 105 +++++ gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradle_mvn_push.gradle | 206 ---------- library/build.gradle | 25 +- library/gradle.properties | 3 - library/proguard-rules.pro | 17 - .../meituan/android/walle/ChannelReader.java | 8 - .../android/walle/WalleChannelReader.java | 103 +++++ mt_maven.gradle | 65 ++++ payload_reader/.gitignore | 1 + payload_reader/README.md | 20 + payload_reader/build.gradle | 11 + .../config/checkstyle/checkstyle.xml | 105 +++++ .../com/meituan/android/walle/ApkUtil.java | 297 ++++++++++++++ .../meituan/android/walle/ChannelInfo.java | 24 ++ .../meituan/android/walle/ChannelReader.java | 69 ++++ .../java/com/meituan/android/walle/Pair.java | 81 ++++ .../meituan/android/walle/PayloadReader.java | 107 +++++ .../walle/SignatureNotFoundException.java | 14 + payload_writer/.gitignore | 1 + payload_writer/README.md | 21 + payload_writer/build.gradle | 12 + .../config/checkstyle/checkstyle.xml | 105 +++++ .../android/walle/ApkSigningBlock.java | 49 +-- .../android/walle/ApkSigningPayload.java | 13 +- .../meituan/android/walle/ChannelWriter.java | 124 ++++++ .../meituan/android/walle/PayloadWriter.java | 270 +++++++++++++ plugin/build.gradle | 15 +- plugin/gradle.properties | 3 - .../meituan/android/walle/ChannelMaker.groovy | 364 +++++++++++------- .../meituan/android/walle/Extension.groovy | 57 +++ .../meituan/android/walle/GradlePlugin.groovy | 84 ++-- .../internal/apk/v2/V2SchemeVerifier.java | 6 +- .../meituan/android/walle/WalleConfig.java | 84 ++++ publish.sh | 22 ++ quality.gradle | 16 + sample/app/build.gradle | 53 --- .../android/walle/sample/MainActivity.java | 12 - sample/build.gradle | 19 - sample/gradle.properties | 21 - sample/gradle/wrapper/gradle-wrapper.jar | Bin 53637 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 - sample/gradlew | 160 -------- sample/gradlew.bat | 90 ----- sample/settings.gradle | 1 - settings.gradle | 2 +- walle-cli/README.md | 69 ++++ walle-cli/build.gradle | 31 ++ walle-cli/config/checkstyle/checkstyle.xml | 105 +++++ .../java/com/meituan/android/walle/Main.java | 54 +++ .../android/walle/WalleCommandLine.java | 56 +++ .../meituan/android/walle/WalleConfig.java | 85 ++++ .../android/walle/commands/Batch2Command.java | 94 +++++ .../android/walle/commands/BatchCommand.java | 86 +++++ .../android/walle/commands/IWalleCommand.java | 9 + .../android/walle/commands/PutCommand.java | 57 +++ .../android/walle/commands/RemoveCommand.java | 42 ++ .../android/walle/commands/ShowCommand.java | 82 ++++ .../CommaSeparatedKeyValueConverter.java | 28 ++ .../com/meituan/android/walle/utils/Fun1.java | 6 + .../com/meituan/android/walle/utils/Util.java | 21 + 87 files changed, 3512 insertions(+), 879 deletions(-) rename {sample/app => app}/.gitignore (100%) create mode 100644 app/build.gradle create mode 100644 app/channel create mode 100644 app/channel_debug create mode 100644 app/config.json rename sample/app/keystore/meituan-debug.keystore => app/keystore/sign-debug.keystore (100%) rename {sample/app => app}/proguard-rules.pro (100%) rename {sample/app => app}/src/main/AndroidManifest.xml (100%) create mode 100644 app/src/main/java/com/meituan/android/walle/sample/MainActivity.java rename {sample/app => app}/src/main/java/com/meituan/android/walle/sample/MyApplication.java (100%) rename {sample/app => app}/src/main/res/layout/activity_main.xml (88%) rename {sample/app => app}/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {sample/app => app}/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {sample/app => app}/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {sample/app => app}/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {sample/app => app}/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename {sample/app => app}/src/main/res/values-w820dp/dimens.xml (100%) rename {sample/app => app}/src/main/res/values/colors.xml (100%) rename {sample/app => app}/src/main/res/values/dimens.xml (100%) rename {sample/app => app}/src/main/res/values/strings.xml (100%) rename {sample/app => app}/src/main/res/values/styles.xml (100%) delete mode 100644 assets/walle.png create mode 100644 config/style/checkstyle.xml delete mode 100644 gradle_mvn_push.gradle delete mode 100644 library/gradle.properties delete mode 100644 library/proguard-rules.pro delete mode 100644 library/src/main/java/com/meituan/android/walle/ChannelReader.java create mode 100644 library/src/main/java/com/meituan/android/walle/WalleChannelReader.java create mode 100644 mt_maven.gradle create mode 100644 payload_reader/.gitignore create mode 100644 payload_reader/README.md create mode 100644 payload_reader/build.gradle create mode 100644 payload_reader/config/checkstyle/checkstyle.xml create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/ApkUtil.java create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/ChannelInfo.java create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/ChannelReader.java create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/Pair.java create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/PayloadReader.java create mode 100644 payload_reader/src/main/java/com/meituan/android/walle/SignatureNotFoundException.java create mode 100644 payload_writer/.gitignore create mode 100644 payload_writer/README.md create mode 100644 payload_writer/build.gradle create mode 100644 payload_writer/config/checkstyle/checkstyle.xml rename plugin/src/main/groovy/com/meituan/android/walle/ApkSigningBlock.groovy => payload_writer/src/main/java/com/meituan/android/walle/ApkSigningBlock.java (60%) rename plugin/src/main/groovy/com/meituan/android/walle/ApkSigningPayload.groovy => payload_writer/src/main/java/com/meituan/android/walle/ApkSigningPayload.java (68%) create mode 100644 payload_writer/src/main/java/com/meituan/android/walle/ChannelWriter.java create mode 100644 payload_writer/src/main/java/com/meituan/android/walle/PayloadWriter.java delete mode 100644 plugin/gradle.properties create mode 100644 plugin/src/main/groovy/com/meituan/android/walle/Extension.groovy create mode 100644 plugin/src/main/java/com/meituan/android/walle/WalleConfig.java create mode 100755 publish.sh create mode 100644 quality.gradle delete mode 100644 sample/app/build.gradle delete mode 100644 sample/app/src/main/java/com/meituan/android/walle/sample/MainActivity.java delete mode 100644 sample/build.gradle delete mode 100644 sample/gradle.properties delete mode 100644 sample/gradle/wrapper/gradle-wrapper.jar delete mode 100644 sample/gradle/wrapper/gradle-wrapper.properties delete mode 100755 sample/gradlew delete mode 100644 sample/gradlew.bat delete mode 100644 sample/settings.gradle create mode 100644 walle-cli/README.md create mode 100644 walle-cli/build.gradle create mode 100644 walle-cli/config/checkstyle/checkstyle.xml create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/Main.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/WalleCommandLine.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/WalleConfig.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/Batch2Command.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/BatchCommand.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/IWalleCommand.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/PutCommand.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/RemoveCommand.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/commands/ShowCommand.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/utils/CommaSeparatedKeyValueConverter.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/utils/Fun1.java create mode 100644 walle-cli/src/main/java/com/meituan/android/walle/utils/Util.java diff --git a/LICENSE b/LICENSE index e69de29..e06d208 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md index 5033e75..3ee31d5 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,195 @@ -## Walle -[![license](http://img.shields.io/badge/license-BSD3-brightgreen.svg?style=flat)](https://github.com/Tencent/tinker/blob/master/LICENSE) +# Walle +[![Release Version](https://api.bintray.com/packages/meituan/maven/com.meituan.android.walle:library/images/download.svg)](https://github.com/Meituan-Dianping/walle/releases) +[![Build Status](https://api.travis-ci.org/Meituan-Dianping/walle.svg?branch=master)](https://travis-ci.org/Meituan-Dianping/walle) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Meituan-Dianping/walle/pulls) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/Meituan-Dianping/walle/master/LICENSE) -支持Android Signature V2 Scheme的渠道包打包神器 +Walle(瓦力):Android Signature V2 Scheme签名下的新一代渠道包打包神器 -![walle.png](assets/walle.png) +瓦力通过在Apk中的`APK Signature Block`区块添加自定义的渠道信息来生成渠道包,从而提高了渠道包生成效率,可以作为单机工具来使用,也可以部署在HTTP服务器上来实时处理渠道包Apk的升级网络请求。 -## 使用说明 -在位于项目的根目录 `build.gradle` 文件中添加walle plugin的依赖 -Add tinker-gradle-plugin as a dependency in your main in the root of your project: +## Quick Start +为了方便大家的使用,我们提供了2种使用方式: -```gradle +* Gradle插件方式,方便快速集成 +* 命令行方式,最大化满足各种自定义需求 + +### Gradle插件使用方式 +#### 配置build.gradle + +在位于项目的根目录 `build.gradle` 文件中添加Walle Gradle插件的依赖, 如下: + +```groovy buildscript { dependencies { - classpath ('com.meituan.android.walle:plugin:0.0.1') + classpath 'com.meituan.android.walle:plugin:1.1.6' } } ``` -Then you need to "apply" the plugin and add dependencies by adding the following lines to your `app/build.gradle`. +并在当前App的 `build.gradle` 文件中apply这个插件,并添加上用于读取渠道号的AAR + +```groovy +apply plugin: 'walle' -```gradle dependencies { - //optional, help to generate the final application - compile('com.tencent.tinker:tinker-android-anno:1.6.0') - //tinker's main Android lib - compile('com.tencent.tinker:tinker-android-lib:1.6.0') + compile 'com.meituan.android.walle:library:1.1.6' } -... -... -apply plugin: 'com.tencent.tinker.patch' ``` -If your app has a class that subclasses android.app.Application, then you need to modify that class, and move all its implements to [SampleApplicationLike](https://github.com/Tencent/tinker/blob/master/tinker-sample-android/app/src/main/java/tinker/sample/android/app/SampleApplicationLike.java) rather than Application: +#### 配置插件 -```java --public class YourApplication extends Application { -+public class SampleApplicationLike extends DefaultApplicationLike { +```groovy +walle { + // 指定渠道包的输出路径 + apkOutputFolder = new File("${project.buildDir}/outputs/channels"); + // 定制渠道包的APK的文件名称 + apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'; + // 渠道配置文件 + channelFile = new File("${project.getProjectDir()}/channel") +} ``` -Now you should change your `Application` class, make it a subclass of [TinkerApplication](https://github.com/Tencent/tinker/blob/master/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/app/TinkerApplication.java). As you can see from its API, it is an abstract class that does not have a default constructor, so you must define a no-arg constructor: +配置项具体解释: + +* apkOutputFolder:指定渠道包的输出路径, 默认值为`new File("${project.buildDir}/outputs/apk")` +* apkFileNameFormat:定制渠道包的APK的文件名称, 默认值为`'${appName}-${buildType}-${channel}.apk'` + 可使用以下变量: + + ``` + projectName - 项目名字 + appName - App模块名字 + packageName - applicationId (App包名packageName) + buildType - buildType (release/debug等) + channel - channel名称 (对应渠道打包中的渠道名字) + versionName - versionName (显示用的版本号) + versionCode - versionCode (内部版本号) + buildTime - buildTime (编译构建日期时间) + fileSHA1 - fileSHA1 (最终APK文件的SHA1哈希值) + flavorName - 编译构建 productFlavors 名 + ``` +* channelFile:包含渠道配置信息的文件路径。 具体内容格式详见:[渠道配置文件示例](app/channel),支持使用#号添加注释。 + +#### 如何获取渠道信息 + +在需要渠道等信息时可以通过下面代码进行获取 ```java -public class SampleApplication extends TinkerApplication { - public SampleApplication() { - super( - //tinkerFlags, which types is supported - //dex only, library only, all support - ShareConstants.TINKER_ENABLE_ALL, - // This is passed as a string so the shell application does not - // have a binary dependency on your ApplicationLifeCycle class. - "tinker.sample.android.SampleApplicationLike"); - } +String channel = WalleChannelReader.getChannel(this.getApplicationContext()); +``` + +#### 如何生成渠道包 + +生成渠道包的方式是和`assemble${variantName}Channels`指令结合,渠道包的生成目录默认存放在 `build/outputs/apk/`,也可以通过`walle`闭包中的`apkOutputFolder`参数来指定输出目录 + +用法示例: + +* 生成渠道包 `./gradlew clean assembleReleaseChannels` +* 支持 productFlavors `./gradlew clean assembleMeituanReleaseChannels` + +#### 更多用法 + +##### 插入额外信息 + +`channelFile`只支持渠道写入,如果想插入除渠道以外的其他信息,请在walle配置中使用`configFile` + +``` +walle { + // 渠道&额外信息配置文件,与channelFile互斥 + configFile = new File("${project.getProjectDir()}/config.json") } ``` -Use `tinker-android-anno` to generate your `Application` is recommended, you just need to add an annotation for your [SampleApplicationLike](https://github.com/Tencent/tinker/blob/master/tinker-sample-android/app/src/main/java/tinker/sample/android/app/SampleApplicationLike.java) class +`configFile`是包含渠道信息和额外信息的配置文件路径。 +配置文件采用json格式,支持为每个channel单独配置额外的写入信息。具体内容格式详见:[渠道&额外信息配置文件示例](app/config.json) 。 + +注意: + +- 此配置项与`channelFile`功能互斥,开发者在使用时选择其一即可,两者都存在时`configFile`优先执行。 +- extraInfo 不要出现以`channel`为key的情况 + +而对应的渠道信息获取方式如下: ```java -@DefaultLifeCycle( -application = "tinker.sample.android.app.SampleApplication", //application name to generate -flags = ShareConstants.TINKER_ENABLE_ALL) //tinkerFlags above -public class SampleApplicationLike extends DefaultApplicationLike +ChannelInfo channelInfo= WalleChannelReader.getChannelInfo(this.getApplicationContext()); +if (channelInfo != null) { + String channel = channelInfo.getChannel(); + Map extraInfo = channelInfo.getExtraInfo(); +} +// 或者也可以直接根据key获取 +String value = WalleChannelReader.get(context, "buildtime"); ``` -How to install tinker? learn more at the sample [SampleApplicationLike](https://github.com/Tencent/tinker/blob/master/tinker-sample-android/app/src/main/java/tinker/sample/android/app/SampleApplicationLike.java). +##### 临时生成某渠道包 + +我们推荐使用channelFile/configFile配置来生成渠道包,但有时也可能有临时生成渠道包需求,这时可以使用: + +- 生成单个渠道包: `./gradlew clean assembleReleaseChannels -PchannelList=meituan` +- 生成多个渠道包: `./gradlew clean assembleReleaseChannels -PchannelList=meituan,dianping` +- 生成渠道包&写入额外信息: + + `./gradlew clean assembleReleaseChannels -PchannelList=meituan -PextraInfo=buildtime:20161212,hash:xxxxxxx` + + 注意: 这里的extraInfo以`key:value`形式提供,多个以`,`分隔。 +- 使用临时channelFile生成渠道包: `./gradlew clean assembleReleaseChannels -PchannelFile=/Users/xx/Documents/channel` +- 使用临时configFile生成渠道包: `./gradlew clean assembleReleaseChannels -PconfigFile=/Users/xx/Documents/config.json` + +使用上述-P参数后,本次打包channelFile/configFile配置将会失效,其他配置仍然有效。 +`-PchannelList`,`-PchannelFile`, `-PconfigFile`三者不可同时使用。 + +### 命令行工具使用方式 + +可以使用命令行工具来支持各类自定义的需求,具体使用方式详见:[Walle CLI 使用说明](walle-cli/README.md) + +### 其他使用方式 -For proguard, we have already made the proguard config automatic, and tinker will also generate the multiDex keep proguard file for you. +为了更好的满足大家的各类自定义需求,我们把对`APK Signing Block`区块进行读写操作的模块进行了封装。 -For more tinker configurations, learn more at the sample [app/build.gradle](https://github.com/Tencent/tinker/blob/master/tinker-sample-android/app/build.gradle). +读写模块的使用说明详见: -## Support -Any problem? +* [APK Signing Block读取模块: payload_reader](payload_reader/README.md) +* [APK Signing Block写入模块: payload_writer](payload_writer/README.md) -1. Learn more from [tinker-sample-android](https://github.com/Tencent/tinker/tree/master/tinker-sample-android). -2. Read the [source code](https://github.com/Tencent/tinker/tree/master). -3. Read the [wiki](https://github.com/Tencent/tinker/wiki) or [FAQ](https://github.com/Tencent/tinker/wiki/Tinker-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) for help. -4. Contact us for help. +## Q&A +- [360加固失效](https://github.com/Meituan-Dianping/walle/wiki/360%E5%8A%A0%E5%9B%BA%E5%A4%B1%E6%95%88%EF%BC%9F)? -## Contributing +## 原理介绍 +对该工具的原理感兴趣的同学,可以移步[美团Android新一代渠道包生成工具](http://tech.meituan.com/android-apk-v2-signature-scheme.html)进行了解。 + +## 注意事项 + +* 使用apksigner重新对Apk签名会导致渠道信息丢失,需要再次写入渠道信息 +* 1.1.3版本起,walle支持对含有comment的apk进行渠道写入, 详见[issue 52](https://github.com/Meituan-Dianping/walle/issues/52) + +## 技术支持 + +* Read The Fucking Source Code +* 通过提交issue来寻求帮助 +* 联系我们寻求帮助 + +## 贡献代码 +* 欢迎提交issue +* 欢迎提交PR + +## 参考 +* [APK Signature Scheme v2](https://source.android.com/security/apksigning/v2.html) +* [Zip Format](https://en.wikipedia.org/wiki/Zip_(file_format)) +* [Android Source Code: ApkSigner](https://android.googlesource.com/platform/build/+/8740e9d) +* [Android Source Code: apksig](https://android.googlesource.com/platform/tools/apksig/) ## License + Copyright 2017 Meituan-Dianping + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sample/app/.gitignore b/app/.gitignore similarity index 100% rename from sample/app/.gitignore rename to app/.gitignore diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..8774528 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,111 @@ +import com.android.build.gradle.api.BaseVariant + +apply plugin: 'com.android.application' +apply plugin: 'walle' +apply from: rootProject.file('quality.gradle') + +buildscript { + repositories { + mavenLocal() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.0' + classpath "com.meituan.android.walle:plugin:latest.integration" + } +} + +android { + + compileSdkVersion rootProject.ext.compileSdkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + + versionCode 101 + versionName "1.0.1" + applicationId "com.meituan.android.walle.sample" + } + + splits { + abi { + enable true + reset() + include 'armeabi', 'x86' + universalApk false + } + } + + signingConfigs { + sign { + storeFile file("keystore/sign-debug.keystore") + storePassword "1234567" + keyAlias "debug" + keyPassword "12345678" + } + } + + buildTypes { + release { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.sign + } + + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + + signingConfig signingConfigs.sign + + applicationIdSuffix 'debug' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + +// productFlavors { +// china { +// } +// international { +// } +// } +} + +configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:support-v4:24.1.1' + compile 'com.android.support:appcompat-v7:24.1.1' + compile project(':library') +} + +walle { + apkOutputFolder = new File("${project.buildDir}/outputs/channels") + apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}-${flavorName}.apk' + //configFile与channelFile两者必须存在一个,否则无法生成渠道包。两者都存在时优先执行configFile + channelFile = new File("${project.getProjectDir()}/channel") + //configFile = new File("${project.getProjectDir()}/config.json") +} + + +// 根据不同的applicationId来配置不同的channelFile/configFile +afterEvaluate { + project.android.applicationVariants.all { BaseVariant variant -> + variant.assemble.doFirst { + if (variant.applicationId.endsWith(".debug")) { + + project.walle.channelFile = new File("${project.getProjectDir()}/channel_debug") + } + } + } +} \ No newline at end of file diff --git a/app/channel b/app/channel new file mode 100644 index 0000000..98bcee1 --- /dev/null +++ b/app/channel @@ -0,0 +1,28 @@ +meituan # 美团 +samsungapps #三星 +hiapk +anzhi +xiaomi # 小米 +91com +gfan +appchina +nduoa +3gcn +mumayi +10086com +wostore +189store +lenovomm +hicloud +meizu +wandou +# Google Play +# googleplay +# 百度 +baidu +# +# 360 +360cn +# +# 应用宝 +myapp \ No newline at end of file diff --git a/app/channel_debug b/app/channel_debug new file mode 100644 index 0000000..102cbe8 --- /dev/null +++ b/app/channel_debug @@ -0,0 +1,2 @@ +meituan # 美团 +samsungapps #三星 \ No newline at end of file diff --git a/app/config.json b/app/config.json new file mode 100644 index 0000000..ea1ebcd --- /dev/null +++ b/app/config.json @@ -0,0 +1,68 @@ +{ + //extraInfo 不要出现以`channel`为key的情况 + /* + 不声明extraInfo的channel默认使用的extraInfo + 如果没有此项则没有默认extraInfo + */ + "defaultExtraInfo": { + "key2": "20161213", + "key": "20161212" + }, + + /* + strategy: + 1. ifNone (默认适用此策略) : 仅当对应channel没有extraInfo时生效 + 2. always : 所有channel都生效,channel中extraInfo的key与defaultExtraInfo重复时,覆盖defaultExtraInfo中的内容。 + */ + + //"defaultExtraInfoStrategy": "always", + + "channelInfoList": [ + { + "channel": "meituan", + // 此channel将使用自己声明的extraInfo + /* + 此alias可以做到写入apk的channel是meituan,而打包时输出的文件名是美团 + 注意:alias不声明时,walle配置apkFileNameFormat中channel就是channel,否则为alias + */ + "alias": "美团", + "extraInfo": { + "buildtime": "20161212", + "hash": "123" + } + }, + { + "channel": "360cn", + // 此channel将使用自己声明的extraInfo + "extraInfo": { + "key": "20161213" + } + }, + { + "channel": "googleplay" + // 此channel将使用defaultExtraInfo + }, + { + "channel": "xiaomi" + // 此channel将使用defaultExtraInfo + }, + { + "channel": "meizu" + // 此channel将使用defaultExtraInfo + }, + { + "channel": "wandoujia", + "excludeDefaultExtraInfo": true + //强制声明不使用defaultExtraInfo,默认false + }, + { + "channel": "myapp", + "excludeDefaultExtraInfo": true, + //强制声明不使用defaultExtraInfo,默认false + "extraInfo": { + // 尽管exclude default,但也可以继续写入自己的。 + "key": "20161212" + } + } + ] +} \ No newline at end of file diff --git a/sample/app/keystore/meituan-debug.keystore b/app/keystore/sign-debug.keystore similarity index 100% rename from sample/app/keystore/meituan-debug.keystore rename to app/keystore/sign-debug.keystore diff --git a/sample/app/proguard-rules.pro b/app/proguard-rules.pro similarity index 100% rename from sample/app/proguard-rules.pro rename to app/proguard-rules.pro diff --git a/sample/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml similarity index 100% rename from sample/app/src/main/AndroidManifest.xml rename to app/src/main/AndroidManifest.xml diff --git a/app/src/main/java/com/meituan/android/walle/sample/MainActivity.java b/app/src/main/java/com/meituan/android/walle/sample/MainActivity.java new file mode 100644 index 0000000..c42aabc --- /dev/null +++ b/app/src/main/java/com/meituan/android/walle/sample/MainActivity.java @@ -0,0 +1,37 @@ +package com.meituan.android.walle.sample; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.meituan.android.walle.ChannelInfo; +import com.meituan.android.walle.WalleChannelReader; + + +public class MainActivity extends AppCompatActivity { + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + findViewById(R.id.read_channel).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + readChannel(); + } + }); + + } + + private void readChannel() { + final TextView tv = (TextView) findViewById(R.id.tv_channel); + final long startTime = System.currentTimeMillis(); + final ChannelInfo channelInfo = WalleChannelReader.getChannelInfo(this.getApplicationContext()); + if (channelInfo != null) { + tv.setText(channelInfo.getChannel() + "\n" + channelInfo.getExtraInfo()); + } + Toast.makeText(this, "ChannelReader takes " + (System.currentTimeMillis() - startTime) + " milliseconds", Toast.LENGTH_SHORT).show(); + } +} diff --git a/sample/app/src/main/java/com/meituan/android/walle/sample/MyApplication.java b/app/src/main/java/com/meituan/android/walle/sample/MyApplication.java similarity index 100% rename from sample/app/src/main/java/com/meituan/android/walle/sample/MyApplication.java rename to app/src/main/java/com/meituan/android/walle/sample/MyApplication.java diff --git a/sample/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml similarity index 88% rename from sample/app/src/main/res/layout/activity_main.xml rename to app/src/main/res/layout/activity_main.xml index f9a033c..fa4c92e 100644 --- a/sample/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,8 +7,7 @@ android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/activity_vertical_margin" - tools:context=".app.MainActivity"> + android:paddingTop="@dimen/activity_vertical_margin"> - +