Files
Xuewang365OSHonor/app/build.gradle

403 lines
17 KiB
Groovy
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
apply plugin: 'com.android.application'
def appName() {
return "XwadOSHonor"
}
def releaseTime() {
return new Date().format("yyyyMMdd_HHmmss", TimeZone.getDefault())
}
android {
namespace "com.xwad.os"
buildToolsVersion "36.0.0"
compileSdkVersion 29
defaultConfig {
applicationId "com.xwad.os"
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
minSdkVersion 23
targetSdkVersion 29
versionCode 44
versionName "1.4.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
//根据需要 自行选择添加的对应cpu类型的.so库。
abiFilters 'armeabi-v7a', 'arm64-v8a'
// 还可以添加 'armeabi', 'x86', 'x86_64', 'mips', 'mips64'
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
aaptOptions.cruncherEnabled = false
aaptOptions.useNewCruncher = false
packagingOptions {
// 根据错误信息,排除具体的重复文件
exclude 'META-INF/DEPENDENCIES'
// 如果还有其他类似冲突如NOTICE, LICENSE文件可以一并排除
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
manifestPlaceholders = [
AMAP_KEY: "db082446a68db8e3ffdc8277313c2e6a"
]
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
dataBinding true
buildConfig true
aidl true
}
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
}
}
signingConfigs {
tuixin {
storeFile file("keystore/tuixin.jks")
storePassword "123456"
keyAlias "universal"
keyPassword "123456"
v2SigningEnabled false
}
}
// def cerFile = file("E:\\Xuewang365\\HonorCer\\HONOR.CER")
applicationVariants.all { variant ->
def variantName = variant.name.capitalize()
// 建议使用 packageApplication 任务,它更明确指向 APK 生成
def packageTask = tasks.findByName("package${variantName}")
if (packageTask) {
packageTask.doLast {
try {
// 1. 配置路径优化:尽量使用 project 属性,避免写死 E:\ 盘符
def cerFile = file("E:\\Xuewang365\\HonorCer\\HONOR.CER")
if (!cerFile.exists()) {
println "⚠️ 未找到证书文件: ${cerFile.path},跳过注入步骤"
return
}
def sdkDir = android.sdkDirectory.path
// def buildToolsVersion = android.buildToolsVersion // 建议动态获取,除非有特定版本要求
def buildToolsVersion = "36.0.0"
def buildToolsPath = "${sdkDir}/build-tools/${buildToolsVersion}"
def aaptPath = "${buildToolsPath}/aapt${org.gradle.internal.os.OperatingSystem.current().isWindows() ? '.exe' : ''}"
def apksignerPath = "${buildToolsPath}/apksigner${org.gradle.internal.os.OperatingSystem.current().isWindows() ? '.bat' : ''}"
// 验证工具是否存在
if (!file(aaptPath).exists()) {
println "❌ 未找到 aapt 工具: ${aaptPath}"
return
}
if (!file(apksignerPath).exists()) {
println "❌ 未找到 apksigner 工具: ${apksignerPath}"
return
}
// 2. 关键优化:精准定位当前 Variant 的输出文件
// 使用 variant.outputs 获取当前构建生成的特定文件
variant.outputs.each { output ->
def apkFile = output.outputFile
if (apkFile == null) {
println "⚠️ APK 文件为 null,跳过处理"
return
}
if (!apkFile.exists()) {
println "⚠️ APK 文件不存在: ${apkFile.absolutePath},跳过处理"
return
}
println "APK地址:${apkFile.absolutePath}"
if (apkFile.name.endsWith(".apk")) {
println "🛠️ 开始对当前 APK 注入: ${apkFile.name}"
try {
// 3. 准备 META-INF 临时结构
def tempBaseDir = new File(project.buildDir, "intermediates/honor_cer_temp/${variant.name}")
def metaInfDir = new File(tempBaseDir, "META-INF")
// 确保清理旧数据
if (metaInfDir.exists()) {
metaInfDir.deleteDir()
}
metaInfDir.mkdirs()
def targetFile = new File(metaInfDir, cerFile.name)
ant.copy(file: cerFile, tofile: targetFile)
// 4. 调用 aapt 注入 - 添加错误输出捕获
println "执行命令: ${aaptPath} add ${apkFile.absolutePath} META-INF/${cerFile.name}"
def aaptResult = exec {
workingDir tempBaseDir
commandLine aaptPath, "add", apkFile.absolutePath, "META-INF/${cerFile.name}"
ignoreExitValue = true // 不立即失败,让我们自己处理
standardOutput = new ByteArrayOutputStream()
errorOutput = new ByteArrayOutputStream()
}
if (aaptResult.exitValue != 0) {
def errorMsg = aaptResult.errorOutput.toString()
println "❌ aapt 执行失败 (退出码: ${aaptResult.exitValue})"
println "错误信息: ${errorMsg}"
println "尝试继续重新签名..."
} else {
println "✅ aapt 注入成功"
}
// 5. 重新签名 (Apksigner)
def signingConfig = variant.signingConfig
if (signingConfig != null && signingConfig.storeFile != null && signingConfig.storeFile.exists()) {
println "执行签名..."
def signResult = exec {
commandLine apksignerPath, "sign",
"--ks", signingConfig.storeFile.absolutePath,
"--ks-pass", "pass:${signingConfig.storePassword}",
"--ks-key-alias", signingConfig.keyAlias,
"--key-pass", "pass:${signingConfig.keyPassword}",
"--v2-signing-enabled", "true",
"--v3-signing-enabled", "true",
apkFile.path
ignoreExitValue = true
standardOutput = new ByteArrayOutputStream()
errorOutput = new ByteArrayOutputStream()
}
if (signResult.exitValue == 0) {
println "✅ [${variant.name}] 注入并修复签名成功!"
} else {
def errorMsg = signResult.errorOutput.toString()
println "❌ [${variant.name}] 签名失败 (退出码: ${signResult.exitValue})"
println "错误信息: ${errorMsg}"
}
} else {
println "❌ [${variant.name}] 签名失败:SigningConfig 配置无效"
}
// 清理临时目录
if (tempBaseDir.exists()) {
tempBaseDir.deleteDir()
}
} catch (Exception e) {
println "❌ 处理 APK 时发生异常: ${e.message}"
e.printStackTrace()
}
}
}
} catch (Exception e) {
println "❌ 证书注入过程发生严重错误: ${e.message}"
e.printStackTrace()
// 不中断构建流程
}
}
}
}
buildTypes {
debug {
versionNameSuffix "-debug"
minifyEnabled false
buildConfigField "String", "platform", '"HONOR"'
signingConfig signingConfigs.tuixin
}
release {
minifyEnabled false
//前一部分代表系统默认的android程序的混淆文件该文件已经包含了基本的混淆声明后一个文件是自己的定义混淆文件
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.tuixin
buildConfigField "String", "platform", '"HONOR"'
}
}
// Add application variant configuration here instead
applicationVariants.all { variant ->
variant.outputs.each { output ->
def buildType = variant.buildType.name
if (buildType.contains("debug")) {
// fileName = "${appName()}_V${defaultConfig.versionName}_${releaseTime()}.apk"
output.outputFileName = "app_debug.apk"
} else {
output.outputFileName = "${appName()}_${variant.versionCode}_V${variant.versionName}_${releaseTime()}_${buildType}.apk"
}
}
}
}
dependencies {
// implementation fileTree(dir: 'libs', include: ['*.jar'])
// compileOnly files('libs/framework.jar')
compileOnly files('libs/magic-android-31.35.6.300.jar')
implementation project(path: ':niceimageview')
implementation project(path: ':FlycoTabLayoutZ_Lib')
implementation project(path: ':verification-view')
implementation project(path: ':PhotoPreview')
//保持1.3.1 更新会报错
implementation 'androidx.appcompat:appcompat:1.3.1'
//2.0.4以上无法预览
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.recyclerview:recyclerview:1.2.1"
// For control over item selection of both touch and mouse driven selection
implementation "androidx.recyclerview:recyclerview-selection:1.1.0"
implementation "androidx.viewpager2:viewpager2:1.0.0"
// Java language implementation
implementation "androidx.fragment:fragment:1.4.1"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.multidex:multidex:2.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.room:room-runtime:2.4.3"
annotationProcessor "androidx.room:room-compiler:2.4.3"
//内存泄漏检测
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
//磁盘缓存
implementation 'com.jakewharton:disklrucache:2.0.2'
//Java WebSocket
implementation "org.java-websocket:Java-WebSocket:1.5.3"
//glide
implementation 'com.github.bumptech.glide:glide:4.13.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.1'
//RxJava
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
//Gson
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.google.zxing:core:3.5.0'
//生命周期管理
implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components-preference:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0'
implementation 'com.jeremyliao:live-event-bus-x:1.7.3'
//MMKV
implementation 'com.tencent:mmkv-static:1.2.14'
//bugly
implementation 'com.tencent.bugly:crashreport:4.1.9.2'
//阿里云推送
implementation 'com.aliyun.ams:alicloud-android-push:3.8.0'
//高德地图定位
implementation 'com.amap.api:location:5.1.0'
//状态栏透明
implementation 'com.gitee.zackratos:UltimateBarX:0.8.0'
//指示器
implementation 'com.github.hackware1993:MagicIndicator:1.7.0' // for androidx
// implementation 'io.github.h07000223:flycoTabLayout:3.0.0'
// implementation 'com.github.liyujiang-gzu:FlycoTabLayout:781b8829a7'
implementation 'com.king.view:circleprogressview:1.1.2'
//工具类
implementation 'com.blankj:utilcodex:1.31.0'
//aria
implementation 'com.arialyy.aria:core:3.8.15'
annotationProcessor 'com.arialyy.aria:compiler:3.8.15'
//videoplayer
implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.16'
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-native:1.0.16'
//验证码输入
// implementation 'com.jacktuotuo.customview:verificationcodeview:1.0.5'
//动态权限框架
implementation 'com.github.getActivity:XXPermissions:18.63'
// 吐司框架https://github.com/getActivity/Toaster
implementation 'com.github.getActivity:Toaster:12.6'
//autosize会改变第三方view的大小
//https://github.com/JessYanCoding/AndroidAutoSize
implementation 'me.jessyan:autosize:1.2.1'
//图片选择
implementation 'io.github.lucksiege:pictureselector:v3.11.1'
// implementation 'com.github.wanglu1209:PhotoViewer:0.50'
// implementation 'com.github.wanggaowan:PhotoPreview:2.5.5'
/*jxw依赖*/
// implementation 'io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.3.2'
// implementation "io.github.cymchad:BaseRecyclerViewAdapterHelper:3.0.14"
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.47'
implementation 'io.github.youth5201314:banner:2.2.3'
implementation 'com.google.android.exoplayer:exoplayer:2.9.4'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.4'
implementation 'com.tencent.tav:libpag:latest.release'
implementation 'com.ufreedom.uikit:FloatingTextLibrary:0.2.0'
implementation 'org.apache.httpcomponents:httpcore:4.4.9'
implementation 'org.apache.httpcomponents:httpclient:4.5.5'
implementation 'org.greenrobot:eventbus:3.3.1'
}
// 在 dependencies 之后添加
project.afterEvaluate {
android.applicationVariants.all { variant ->
variant.javaCompileProvider.get().options.bootstrapClasspath = files(
file('libs/framework.jar'),
android.getBootClasspath()
)
}
}
//preBuild {
// doLast {
// def imlFile = file(project.name + ".iml")
//// def imlFile = file("..\\.idea\\modules\\" + project.name + "\\" + rootProject.name + "." + project.name + ".iml")
// println 'Change ' + project.name + '.iml order'
// try {
// def parsedXml = (new XmlParser()).parse(imlFile)
// def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
// parsedXml.component[1].remove(jdkNode)
// def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
// println 'what' + sdkString
// new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
// groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
// } catch (FileNotFoundException e) {
// // nop, iml not found
// println "no iml found"
// }
// }
//}