mirror of
https://github.com/RxReader/walle_kit.git
synced 2025-08-06 15:19:02 +08:00
移除 cli
This commit is contained in:
11
README.md
11
README.md
@ -44,9 +44,11 @@ zipalign -p -f -v 4 input.apk output.apk
|
|||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
// android/app/build.gradle
|
// android/app/build.gradle
|
||||||
apply from: "${project(":walle_kit").projectDir}/walle_kit_v2.gradle" // 推荐(非cli方式,不支持360加固)
|
apply from: "${project(":walle_kit").projectDir}/walle_kit_v3.gradle" // 推荐(非cli方式,不支持360加固、不支持腾讯乐固)
|
||||||
// 或
|
// 或
|
||||||
apply from: "${project(":walle_kit").projectDir}/walle_kit.gradle" // 不推荐(cli方式,支持360加固)
|
apply from: "${project(":walle_kit").projectDir}/walle_kit_v2.gradle" // 推荐(非cli方式,不支持360加固、支持腾讯乐固)
|
||||||
|
// 或
|
||||||
|
apply from: "${project(":walle_kit").projectDir}/walle_kit.gradle" // 不推荐(cli方式,支持360加固、支持腾讯乐固)
|
||||||
```
|
```
|
||||||
|
|
||||||
* fileNameFormat
|
* fileNameFormat
|
||||||
@ -66,6 +68,11 @@ apply from: "${project(":walle_kit").projectDir}/walle_kit.gradle" // 不推荐
|
|||||||
* [配置文件示例 - channel](example/android/app/channel)
|
* [配置文件示例 - channel](example/android/app/channel)
|
||||||
* [配置文件示例 - channel.json](example/android/app/channel.json)
|
* [配置文件示例 - channel.json](example/android/app/channel.json)
|
||||||
|
|
||||||
|
### walle_kit_v3.gradle
|
||||||
|
|
||||||
|
> 应用宝上架,已不再强制要求加固
|
||||||
|
> 用法同 walle_kit_v2.gradle 一致,不同的是已不再支持腾讯乐固功能
|
||||||
|
|
||||||
### walle_kit_v2.gradle
|
### walle_kit_v2.gradle
|
||||||
|
|
||||||
* without flavors
|
* without flavors
|
||||||
|
237
android/walle_kit_v3.gradle
Normal file
237
android/walle_kit_v3.gradle
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
//
|
||||||
|
//使用方法
|
||||||
|
//
|
||||||
|
//apply from: 'walle.gradle'
|
||||||
|
//
|
||||||
|
//android {
|
||||||
|
// productFlavors {
|
||||||
|
// prod {...}
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// walleConfigs {
|
||||||
|
// prod {
|
||||||
|
// enabled = true
|
||||||
|
//
|
||||||
|
// outputDir = file("${project.buildDir}/outputs/apk/${flavorName}/${buildType}/walle") // 默认:file("${project.buildDir}/outputs/apk/${flavorName}/${buildType}/walle")
|
||||||
|
// fileNameFormat = '${appName}-${buildType}-${channelId}.apk' // 默认:'${appName}-${buildType}-${channelId}.apk'
|
||||||
|
//// channelType = 0 // 0:默认;1:json
|
||||||
|
// channelFile = file('channel')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//walle {
|
||||||
|
// enabled = false
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
|
||||||
|
// 阿里云jcenter镜像
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
|
classpath 'com.meituan.android.walle:payload_writer:1.1.7'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Walle {
|
||||||
|
final String name
|
||||||
|
Boolean enabled
|
||||||
|
File outputDir
|
||||||
|
String fileNameFormat
|
||||||
|
Integer channelType
|
||||||
|
File channelFile
|
||||||
|
|
||||||
|
Walle(String name = 'default') {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
void validate() {
|
||||||
|
if (enabled == null || !enabled.booleanValue()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (channelType != null && channelType != 0 && channelType != 1) {
|
||||||
|
throw new RuntimeException("walle channel type is unsupported for variant '$name'")
|
||||||
|
}
|
||||||
|
if (channelFile == null) {
|
||||||
|
throw new RuntimeException("walle channel file is null for variant '$name'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Walle mergeWith(Walle other) {
|
||||||
|
if (other == null) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
def mergeWalle = new Walle(name == 'default' ? other.name : (other.name == 'default' ? name : "$name${other.name.capitalize()}"))
|
||||||
|
mergeWalle.enabled = other.enabled != null ? other.enabled : enabled
|
||||||
|
mergeWalle.outputDir = other.outputDir ?: outputDir
|
||||||
|
mergeWalle.fileNameFormat = other.fileNameFormat ?: fileNameFormat
|
||||||
|
mergeWalle.channelType = other.channelType ?: channelType
|
||||||
|
mergeWalle.channelFile = other.channelFile ?: channelFile
|
||||||
|
return mergeWalle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: WallePlugin
|
||||||
|
|
||||||
|
class WallePlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void apply(Project target) {
|
||||||
|
target.extensions.create('walle', Walle.class)
|
||||||
|
target.plugins.withId('com.android.application') {
|
||||||
|
def baseWalle = target.walle
|
||||||
|
def walleConfigs = target.container(Walle.class)
|
||||||
|
target.android.extensions.walleConfigs = walleConfigs
|
||||||
|
target.android.applicationVariants.whenObjectAdded { variant ->
|
||||||
|
def mergeWalle = null
|
||||||
|
List<Walle> flavorWalles = variant.productFlavors?.stream()?.map{flavor -> walleConfigs.findByName(flavor.name)}?.collect()?.toList() ?: Collections.emptyList()
|
||||||
|
def buildTypeWalle = walleConfigs.findByName(variant.buildType.name)
|
||||||
|
if (buildTypeWalle == null && (variant.buildType.name == 'debug' || variant.buildType.name == 'profile')) {
|
||||||
|
buildTypeWalle = new Walle(variant.buildType.name)
|
||||||
|
buildTypeWalle.enabled = false
|
||||||
|
}
|
||||||
|
// buildType > flavor > base
|
||||||
|
List<Walle> walles = []
|
||||||
|
walles.add(baseWalle)
|
||||||
|
walles.addAll(flavorWalles)
|
||||||
|
walles.add(buildTypeWalle)
|
||||||
|
for (def walle in walles) {
|
||||||
|
if (mergeWalle == null) {
|
||||||
|
mergeWalle = walle
|
||||||
|
} else {
|
||||||
|
mergeWalle = mergeWalle.mergeWith(walle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeWalle?.validate()
|
||||||
|
|
||||||
|
variant.assemble.doLast {
|
||||||
|
walleWork(target, variant, mergeWalle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.afterEvaluate {
|
||||||
|
if (!target.plugins.hasPlugin('com.android.application')) {
|
||||||
|
target.logger.warn("The Android Gradle Plugin was not applied. Gradle Walle will not be configured.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void walleWork(Project target, def variant, Walle walle) {
|
||||||
|
if (walle == null || walle.enabled == null || !walle.enabled.booleanValue()) {
|
||||||
|
target.logger.info("Gradle Walle is disabled for variant '${variant.name}'.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!variant.signingReady && !variant.outputsAreSigned) {
|
||||||
|
target.logger.error("Signing not ready for Gradle Walle. Be sure to specify a signingConfig for variant '${variant.name}'.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println '--- walle ---'
|
||||||
|
|
||||||
|
def apkFile = variant.outputs.first().outputFile as File
|
||||||
|
println "apk file: ${apkFile.path}"
|
||||||
|
|
||||||
|
def v2SigningEnabled = v2SigningEnabled(variant)
|
||||||
|
println "v2SigningEnabled: ${v2SigningEnabled}"
|
||||||
|
if (!v2SigningEnabled) {
|
||||||
|
throw new RuntimeException("${apkFile.path} has no v2 signature in Apk Signing Block!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预备输出目录
|
||||||
|
def outputDir = walle.outputDir
|
||||||
|
if (outputDir == null) {
|
||||||
|
outputDir = new File(apkFile.parentFile, 'walle')
|
||||||
|
}
|
||||||
|
def channelsDir = new File(outputDir, 'channels')
|
||||||
|
if (!channelsDir.exists()) {
|
||||||
|
channelsDir.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
def nameVariantMap = [
|
||||||
|
'appName' : target.name,
|
||||||
|
'projectName': target.rootProject.name,
|
||||||
|
'buildType' : variant.buildType.name,
|
||||||
|
'versionName': variant.versionName,
|
||||||
|
'versionCode': variant.versionCode,
|
||||||
|
'packageName': variant.applicationId,
|
||||||
|
'flavorName' : variant.flavorName,
|
||||||
|
'channelId': 'channel'
|
||||||
|
]
|
||||||
|
|
||||||
|
def fileNameFormat = walle.fileNameFormat ?: '${appName}-${buildType}-${channelId}.apk'
|
||||||
|
def targetApkFile = new File(outputDir, new groovy.text.SimpleTemplateEngine().createTemplate(fileNameFormat).make(nameVariantMap).toString())// new File(outputDir, apkFile.name)
|
||||||
|
|
||||||
|
// 复制
|
||||||
|
java.nio.file.Files.copy(apkFile.toPath(), targetApkFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
|
||||||
|
println "target apk file: ${targetApkFile.path}"
|
||||||
|
|
||||||
|
// 读取渠道信息
|
||||||
|
def channels = []
|
||||||
|
if (walle.channelType == 1) {
|
||||||
|
def slurper = new groovy.json.JsonSlurper()
|
||||||
|
channels = slurper.parse(walle.channelFile)
|
||||||
|
} else {
|
||||||
|
walle.channelFile.eachLine { line ->
|
||||||
|
def lineTrim = line.trim()
|
||||||
|
if (lineTrim.length() != 0 && !lineTrim.startsWith("#")) {
|
||||||
|
def channelId = line.split("#").first().trim()
|
||||||
|
if (channelId.length() != 0) {
|
||||||
|
channels.add(['alias': channelId, 'channelId': channelId])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channels.each { channel ->
|
||||||
|
nameVariantMap['channelId'] = channel.channelId
|
||||||
|
def storeDir = channelsDir
|
||||||
|
if (channel.storeDir != null) {
|
||||||
|
storeDir = new File(storeDir, channel.storeDir)
|
||||||
|
if (!storeDir.exists()) {
|
||||||
|
storeDir.mkdirs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def channelApkFile = new File(storeDir, new groovy.text.SimpleTemplateEngine().createTemplate(fileNameFormat).make(nameVariantMap).toString())
|
||||||
|
|
||||||
|
def originalApkFile = targetApkFile
|
||||||
|
|
||||||
|
if (originalApkFile != targetApkFile) {
|
||||||
|
println "${channel.alias ?: channel.channelId} original apk file: ${originalApkFile.path}"
|
||||||
|
}
|
||||||
|
println "${channel.alias ?: channel.channelId} channel apk file: ${channelApkFile.path}"
|
||||||
|
|
||||||
|
writePayload(target, channel, originalApkFile, channelApkFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
println '--- walle ---'
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean v2SigningEnabled(variant) {
|
||||||
|
def signingConfig = variant.signingConfig
|
||||||
|
return signingConfig.v2SigningEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
void writePayload(Project target, def channel, File apkFile, File channelApkFile) {
|
||||||
|
java.nio.file.Files.copy(apkFile.toPath(), channelApkFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
com.meituan.android.walle.ChannelWriter.put(channelApkFile, channel.channelId, channel.extraInfo)
|
||||||
|
}
|
||||||
|
}
|
@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
|
|||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
// walle
|
// walle
|
||||||
apply from: "${project(":walle_kit").projectDir}/walle_kit_v2.gradle"
|
apply from: "${project(":walle_kit").projectDir}/walle_kit_v3.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion flutter.compileSdkVersion
|
compileSdkVersion flutter.compileSdkVersion
|
||||||
@ -59,15 +59,6 @@ android {
|
|||||||
release {
|
release {
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
// // [访问管理](https://console.cloud.tencent.com/cam/capi)
|
|
||||||
// // [移动应用安全](https://console.cloud.tencent.com/ms/reinforce/list)
|
|
||||||
// tencent {
|
|
||||||
// secretId = 'xxx'
|
|
||||||
// secretKey = 'xxx'
|
|
||||||
//// region = 'ap-guangzhou' // 可选:'ap-guangzhou'、'ap-shanghai',默认:'ap-guangzhou'
|
|
||||||
// channels = ['tencent', 'tencent-alias']
|
|
||||||
// }
|
|
||||||
|
|
||||||
outputDir = file("${project.buildDir}/outputs/apk/walle") // 默认:file("${project.buildDir}/outputs/apk/${flavorName}/${buildType}/walle")
|
outputDir = file("${project.buildDir}/outputs/apk/walle") // 默认:file("${project.buildDir}/outputs/apk/${flavorName}/${buildType}/walle")
|
||||||
fileNameFormat = '${appName}-${buildType}-${channelId}.apk' // 默认:'${appName}-${buildType}-${channelId}.apk'
|
fileNameFormat = '${appName}-${buildType}-${channelId}.apk' // 默认:'${appName}-${buildType}-${channelId}.apk'
|
||||||
// channelType = 0 // 0:默认;1:json
|
// channelType = 0 // 0:默认;1:json
|
||||||
|
@ -13,6 +13,8 @@ tencent
|
|||||||
aliyun
|
aliyun
|
||||||
# 华为
|
# 华为
|
||||||
huawei
|
huawei
|
||||||
|
# 荣耀
|
||||||
|
honor
|
||||||
# Oppo
|
# Oppo
|
||||||
oppo
|
oppo
|
||||||
# Vivo
|
# Vivo
|
||||||
|
@ -36,6 +36,11 @@
|
|||||||
"channelId": "huawei",
|
"channelId": "huawei",
|
||||||
"storeDir": "market"
|
"storeDir": "market"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"alias": "荣耀",
|
||||||
|
"channelId": "honor",
|
||||||
|
"storeDir": "market"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"alias": "Oppo",
|
"alias": "Oppo",
|
||||||
"channelId": "oppo",
|
"channelId": "oppo",
|
||||||
|
@ -7,7 +7,7 @@ packages:
|
|||||||
name: async
|
name: async
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.9.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -21,21 +21,14 @@ packages:
|
|||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -56,7 +49,7 @@ packages:
|
|||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -94,28 +87,28 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.12"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.4"
|
version: "0.1.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.8.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -134,7 +127,7 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.9.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -155,21 +148,21 @@ packages:
|
|||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.12"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
Reference in New Issue
Block a user