一、使用Androis Studio自帶的productFlavors
productFlavors的功能非常強大,但用起來真的太慢,即使不是很大的項目,你也受不了那個速度。之所以慢,也是因為他的強大。比較適合Google play發布吧,畢竟人家支持根據機型下載不同的安裝包(比如按平臺打包so文件)。國內的情況,一般都不支持,渠道也只不過是用一個字符串區分,其他都一樣。確實沒必要用productFlavors。這里還是記錄下用法:
1、在app module 的builde.gradle 的android{}閉包下配置
//多渠道打包,下面是需要配置的渠道,名稱自定義,自己能區分就行
productFlavors {
alphaTest {}
alibaba {}
xiaomi {}
googlePlay {}
official {}
yingyongbao{}
huawei{}
qh360 {}
baidu {}
kuan {}
}
productFlavors.all {//會替換AndroidManifest下配置的變量,達到區分不同渠道的目的
flavor -> flavor.manifestPlaceholders = [STORE_CHANNEL_VALUE: name]
}
2、AndroidManifest下application標簽下添加
<meta-data
android:name="STORE_CHANNEL"
android:value="${STORE_CHANNEL_VALUE}"/>
3、獲取渠道信息的方法
//可能返回空,需要自己判斷
public static String getAppChannel(Context context) {
ApplicationInfo appInfo;
try {
appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString("STORE_CHANNEL");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
二、使用一些開源的工具,這里推薦騰訊的VasDolly
1、先說些相關的
這里推薦一片文章,關于V1,V2簽名,以及多渠道打包工具的原理:
借騰訊開源 VasDolly,談談 Android 簽名和多渠道打包的原理
VasDolly Github網址:
https://github.com/Tencent/VasDolly
詳細的使用方法,上面的網址里的文檔已經寫的很清楚了。有一個注意點就是目前按照github文檔(2018/3/9)根據基礎包生成多渠道包的rebuildChannel不能配置文件名,實際上也是可以的,但不是那么直接(這里和維護的工程師交流過了,說會加上說明)。
rebuildChannel {
//指定渠道文件
//channelFile = file("/Users/leon/Downloads/testReChannel.txt")
//注意這個文件名base.apk
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/base.apk"
releaseOutputDir = new File(project.buildDir, "rebuildChannel/release")
//快速模式:生成渠道包時不進行校驗(速度可以提升10倍以上)
isFastMode = false
}
文檔里沒有說明的一個規則:渠道名會替換基礎包名稱里的base字符串。
以上面的配置為例,假設你有渠道名是kuan,那么執行rebuildChannel后的輸出的文件名就是kuan.apk(base--->kuan)。
如果上面的baseReleaseApk名稱做下修改:
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/",
"apk-base/app_base_V1.0_release.apk"
那么最后輸出的文件名就是app_kuan_V1.0_release.apk
2、結合AndResGuard使用VasDolly
2.1、添加依賴
Project的build.gradle
buildscript {
repositories {
jcenter()
google()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.11'
classpath 'com.leon.channel:plugin:1.1.7'
}
}
主module app的build.gradle添加插件
apply plugin: 'AndResGuard'
apply plugin: 'channel'
主module app的build.gradle添加依賴(只有這一個,用于獲取渠道信息,其他方面這兩個工具都不涉及編譯過程)
dependencies {
api 'com.leon.channel:helper:1.1.7'
}
主module app的build.gradle 配置
rebuildChannel {//從此,打包效率提高十倍以上,即使不開FastMode
//這里的目錄都是自己定義的,我這里是動態的設置包的名稱的,由于versionName比較長,就截取了一段
baseDebugApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}-base-debug.apk")
debugOutputDir = new File("C:/Users/Bright/Desktop/", "rebuildChannel/debug")
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}-base-release.apk")
releaseOutputDir = new File("C:/Users/Bright/Desktop/", "rebuildChannel/release")
//快速模式:生成渠道包時不進行校驗(速度可以提升10倍以上)
isFastMode = false
}
andResGuard {
// mappingFile = file("./resource_mapping.txt")
mappingFile = null
// 使用v2簽名和7zip壓縮是沖突的(但他是不會報錯的)。
// 如果用了V2,這里就必須false,不然生成的包無法安裝。
use7zip = false
useSign = true
// 打開這個開關,會keep住所有資源的原始路徑,只混淆資源的名字
keepRoot = false
whiteList = [
"R.mipmap.ic_launcher",
"R.mipmap.ic_launcher_round",
"R.drawable.push_small"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.11'
//path = "/usr/local/bin/7za"
}
//這里配置的是輸出的目錄,名稱是動態的,可以參考下這種寫法buildTypes就是release/debug/...看你配置了幾種了
finalApkBackupPath = "C:/Android/Project-3.0/ProjectName/apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}" +
"-base-" +
"release.apk"
}
主module app的build.gradle android{}閉包里配置簽名信息,這里同時使用了V1、V2簽名:
signingConfigs {
//在這里配置相關的簽名信息
keyStore {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def keystoreFilePath = properties.getProperty("KEY_STORE_FILE_PATH")
def storePsw = properties.getProperty("KEY_STORE_PASSWORD")
def alias = properties.getProperty("KEY_ALIAS")
def keyPsw = properties.getProperty("KEY_PASSWORD")
storeFile file(keystoreFilePath)
storePassword storePsw
keyAlias alias
keyPassword keyPsw
v1SigningEnabled true
v2SigningEnabled true
}
}
channel.txt:
alibaba
xiaomi
googlePlay
official
yingyongbao
huawei
qh360
baidu
channel.txt我是放在Project根目錄下,然后在gradle.properties里配置的:
channel_file=channel.txt
你也可以在rebuildChannel{}閉包里配置,具體參照VasDolly的Github文檔
獲取渠道信息的方法:
public static String getAppChannel(Context context) {
String channel = ChannelReaderUtil.getChannel(context.getApplicationContext());
if (channel == null) {//防止debug直接安裝時,獲取為空,事實上,也只有release時才需要多渠道
return "alphaTest";
} else {
return channel;
}
}
最后,先resguardRelease
生成基礎包,然后rebuildChannel生成多渠道包,收工。
也可以編輯gradle task,做成一個task搞定(其實沒多大差別了)。