AndroidStudio3.2的多渠道自動化打包問題
多渠道打包的配置
網上有很多利用第三方框架進行打包的平臺,例如友盟,美團的瓦力等等,這些框架確實功能強大,但是對於自己的專案,如果只是為了打個多渠道包就去引入一個第三方框架,實在難登大雅,下邊就介紹一下我們利用Gradle在AndroidStudio中配置多渠道打包的操作,這裡指定了as版本是因為筆者目前使用的AndroidStudio是3.2的版本,目前的最新版遇到有個別問題(在低版本上不知是否依然存在),故有此說。
// flavorDimensions "versionCode" // flavor dimension 它的維度就是該版本號,統一維度, productFlavors { // 一下括號中的 dimension "versionCode"可以刪除 Alia { } Xiaomi { } Huawei { } Vivo { } Oppo { } Tencent { // dimension "versionCode" } } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.name] }
上文的 flavorDimensions “versionCode” 也可以寫在defaultconfig中,做統一緯度配置
defaultConfig { applicationId appConfig.appId minSdkVersion versions.minSdkVersion targetSdkVersion versions.targetSdkVersion versionCode versions.versionCode versionName versions.versionName flavorDimensions "versionCode" // flavor dimension 它的維度就是該版本號,統一維度, testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }
android studio多渠道打包錯誤
如果在多渠道配置的時候沒有指定統一的緯度,也就是沒有flavorDimensions 屬性,就會有以下錯誤
AAPT2 的錯誤,要先在自己程式碼中找問題,不要看見他就是false,已經不好使了。
- 如果在多渠道配置的時候沒有指定統一的緯度,也就是沒有flavorDimensions 屬性,就會有以下錯誤
Daemon: AAPT2 aapt2-3.2.1-4818971-windows Daemon #0
此時千萬不要把aapt2設定false來解決,現在這個方法已經過時被棄用了,所以在新版AndroidStudio3.2中多渠道打包配置是必須要指定統一緯度的,由此也可見,看到了
- Error:error: failed to read PNG signature: file does not start with PNG signature
這個就是你的資原始檔有問題,可能是某一個png圖片解析失敗了,你可以編輯這張圖片另存一下再使用,或者將png的圖片修改一下字尾格式,例如改成jpg格式。此問題可解。
完整的build.gralde檔案
裡邊隱藏了專案簽名檔案和配置資訊,還有第三方的appkey,APPID等重要資訊。為了安全考慮,都寫在了一個自定義的.gradle檔案中,這個自定義檔案在版本控制的時候是不用上傳的,這樣就有效保護了專案的安全,就算別人拿到了你的原始碼,沒有這些東西,他什麼也幹不了
自定義config.gardle樣例格式
ext.versions = [
// 本地倉庫版本
compileSdkVersion: 26,
buildToolsVersion: "26.0.3",
minSdkVersion : 18,
targetSdkVersion : 26,
versionCode : 4,
versionName : "1.2.1",
supportVersion : "25.3.0",
loggerVersion : "2.2.0"
]
// app 相關資訊總配置
ext.appConfig = [
appId : 'dingshi.com.hibook',
betaName : '@string/app_name',
proName : '@string/app_name',
// keyAlias : 'hibook',
// keyPassword : 'hibook',
// storeFile : 'hibook.jks',
// storePassword: 'hibook',
GETUI_APP_ID : "PhmRY1Uy8A9VrK2L2H8Qz3",
GETUI_APP_KEY : "VXJjCzXD0M7UqsPzFbXtT7",
GETUI_APP_SECRET : "ZmO60vhutt6NxMauNZJjl8",
// EASEMOB_DEBUG : "1191180110115352#hello-book-dev",
EASEMOB_DEBUG : "1191180110115352#hello-book",
EASEMOB_RELEASE : "1191180110115352#hello-book",
LOCALHOST_DEBUG : "\"http://api.linkbooker.com/\"",
// LOCALHOST_DEBUG : "\"http://testapi.linkbooker.com/\"",
LOCALHOST_RELEASE: "\"http://api.linkbooker.com/\""
]
ext.channel = [
HIBOOK_TEST_NAME: "test_channel",
Baidu : "Baidu",
Xiaomi : "Xiaomi",
Huawei : "huawei",
Vivo : "vivo",
Oppo : "oppo",
Tencent : "tencent",
Server : "server"
]
配置多渠道資訊的module下的build.gardle
apply plugin: 'com.android.application'
apply from: "$rootDir/config.gradle"
android {
signingConfigs {
config {
keyAlias appConfig.keyAlias
keyPassword appConfig.keyPassword
storeFile file(appConfig.storeFile)
storePassword appConfig.storePassword
}
}
compileSdkVersion versions.compileSdkVersion
defaultConfig {
applicationId appConfig.appId
minSdkVersion versions.minSdkVersion
targetSdkVersion versions.targetSdkVersion
versionCode versions.versionCode
versionName versions.versionName
flavorDimensions "versionCode" // flavor dimension 它的維度就是該版本號,統一維度,
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
buildConfigField "String", "LOCALHOST", appConfig.LOCALHOST_RELEASE
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable true
jniDebuggable true
renderscriptDebuggable true
zipAlignEnabled true
}
debug {
buildConfigField "String", "LOCALHOST", appConfig.LOCALHOST_DEBUG
debuggable true
jniDebuggable true
signingConfig signingConfigs.config
renderscriptDebuggable true
minifyEnabled true
pseudoLocalesEnabled true
zipAlignEnabled true
}
}
buildToolsVersion versions.buildToolsVersion
// dexOptions {
// incremental true
// }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// flavorDimensions "versionCode" // flavor dimension 它的維度就是該版本號,統一維度,
productFlavors {
// 一下括號中的 dimension "versionCode"可以刪除
Alia {
}
Xiaomi {
}
Huawei {
}
Vivo {
}
Oppo {
}
Tencent {
// dimension "versionCode"
}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.name]
}
//***AS3.0版本 設定apk名稱***
android.applicationVariants.all { variant ->
variant.outputs.all {
if (variant.name.endsWith("Debug")) {
//debug包
outputFileName = "$applicationId _v${defaultConfig.versionName}_${getDate()}_code${defaultConfig.versionCode}_debug.apk"
} else {
//release包
variant.outputs.each { output ->
def appName = 'athesismentor'
def oldFile = output.outputFile
def buildName
def releaseApkName
variant.productFlavors.each { product ->
buildName = product.name
}
releaseApkName = appName + '-' + buildName + '-' + getDate() + '_release.apk'
// output.outputFile = new File(oldFile.parent, releaseApkName)
outputFileName =releaseApkName
// outputFileName = "$applicationId _v${defaultConfig.versionName}_code${defaultConfig.versionCode}_${getDate()}_release.apk"
}
}
}
}
}
//獲取時間戳
static def getDate() {
def date = new Date()
def formattedDate = date.format('yyyy-MM-dd-HH_mm')
return formattedDate
}
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion versions.supportVersion
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "com.orhanobut:logger:$versions.utilVersion"
}
##Gradle3.0以上(3.3)版本生成自動化apk名稱有用如下方法替換
上述生成自定義apk的方法是寫在android{}節點下的,以下方法要寫在android{ buildType{生成自定義apk名稱 } }節點下,如下:
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace("之前系統預設名稱.apk", "想要替換的名稱${defaultConfig.versionName}_${getDate()}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
當然,上邊的getDate方法還是和原來的一樣,寫在android{}節點以外的根節點下
//獲取時間戳
static def getDate() {
def date = new Date()
def formattedDate = date.format('MMddHHmm')
return formattedDate
}