Android打包之多版本、多環境、多渠道
多版本,多環境,多渠道,這個算說清楚了
----------------------------------------------------------------------------------------------------
轉自:https://www.jianshu.com/p/872dc6f89cb4
如果每一次在不同網路環境間切換,都需要更改程式碼,然而重新打包,那未免有點低效。下面是我的實踐探索,看網上很多人都是根據buildType來切換網路環境,感覺有點不好,因為網路環境可能很多種,而buildType我們一般是2種,而且,不同網路環境的包最好能同時安裝在手機上,以便我們除錯。最好,我一看這個包的名稱和圖示,就能知道這是什麼環境的包。
一、概述
1.多版本
基於buildTypes
(1)debug:除錯版本,無混淆
(2)release:釋出版本,有混淆、壓縮
2.多環境
基於productFlavors
(1)develop:開發環境,開發和自測時使用
(2)check:測試環境,克隆一份生產環境的配置,在這裡測試通過後,再發布到生產環境。
之所以沒命名為test是因為在gradle編譯時:ProductFlavor names cannot start with 'test'
(3)product:生產環境,正式提供服務的。
3.多渠道
基於Android新的應用簽名方案APK Signature Scheme v2中的APK Signing Block區塊
我這裡使用的是美團封裝的Walle庫。使用Walle庫請確保你的Android Gradle 外掛版本在2.2.0以上。
為什麼不直接使用productFlavors來打包多渠道?因為productFlavors打多渠道包太慢了,打30個包差不多十幾分鍾,無法忍受!
為什麼不使用美團之前基於META-INF進行渠道標識的方案?因為Android7.0之後的這種黑科技已經失效了!
二、示例
1、配置build.gradle
(1) 在位於專案的根目錄 build.gradle 檔案中新增Walle Gradle外掛的依賴, 如下:
buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.meituan.android.walle:plugin:1.0.3' } }
(2) 在當前App的 build.gradle 檔案中apply這個外掛,並新增上用於讀取渠道號的aar
apply plugin: 'com.android.application'
apply plugin: 'walle'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
keyAlias KEY_ALIAS
keyPassword KEY_PASSWORD
storeFile rootProject.file(KEYSTORE_FILE)
storePassword KEYSTORE_PASSWORD
}
}
buildTypes {
//除錯版本,無混淆
debug {
minifyEnabled false
signingConfig signingConfigs.release
}
//釋出版本,有混淆
release {
minifyEnabled true
zipAlignEnabled true
shrinkResources true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
//開發環境
develop {
buildConfigField "int", "ENV_TYPE", "1"
applicationId 'om.soubu.walledemo.develop'
manifestPlaceholders = [
app_name: "開-WalleDemo",
app_icon: "@drawable/icon_develop"
]
}
//測試環境
check {
buildConfigField "int", "ENV_TYPE", "2"
applicationId 'om.soubu.walledemo.check'
manifestPlaceholders = [
app_name: "測-WalleDemo",
app_icon: "@drawable/icon_check"
]
}
//生產環境
product {
buildConfigField "int", "ENV_TYPE", "3"
applicationId 'com.soubu.walledemo.product'
manifestPlaceholders = [
app_name: "WalleDemo",
app_icon: "@drawable/icon_product"
]
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.0'
testCompile 'junit:junit:4.12'
compile 'com.meituan.android.walle:library:1.0.3'
}
(3) 這裡,我根據不同的環境生成了不同包名的apk,方便在手機上同時安裝多個環境的應用。為了讓gradle動態更改apk的名稱和圖示,我們需要在manifest檔案中使用${app_icon}、${app_name}等佔位符
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.soubu.walledemo">
<application
android:allowBackup="true"
android:icon="${app_icon}"
android:label="${app_name}"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
(4) 在程式碼中獲取多渠道資訊
String channel = WalleChannelReader.getChannel(getApplicationContext());
(5) 在程式碼中獲取多環境資訊
int envType = BuildConfig.ENV_TYPE;
這裡的BuildConfig是由gradle動態生成的:
package com.soubu.walledemo;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "om.soubu.walledemo.develop";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "develop";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from product flavor: develop
public static final int ENV_TYPE = 1;
}
而ENV_TYPE這個欄位其實就來自於我們的build.gradle:
productFlavors {
//開發環境
develop {
buildConfigField "int", "ENV_TYPE", "1"
applicationId 'om.soubu.walledemo.develop'
manifestPlaceholders = [
app_name: "開-WalleDemo",
app_icon: "@drawable/icon_develop"
]
}
{
這裡我們最好定義一個常量類區分這些環境的型別:
public class EnvType {
public static final int DEVELOP = 1;//開發環境
public static final int CHECK = 2;//測試環境
public static final int PRODUCT = 3;//正式環境
}
2、打包多環境
這裡我們直接執行assemble命令,打包所有的buildType*productFlavors
或者使用命令列也可以:
gradle assemble
執行結果:26秒搞定6個包:2個版本*3個環境
這裡我們可以看到debug包都是1.4M,而release包都是0.7M,顯然,我們的混淆和壓縮配置是生效了的,雖然這裡我並沒寫混淆規則
我們分別安裝3個環境的包到自己的手機上:
看三個包的名稱和圖示都不一樣,顯然我們之前在manifest檔案中配置的佔位符生效了。
然後我們點進去分別看看這3個app的區別:
這樣,我們就可以在程式碼中,根據環境欄位envType的不同,來選擇不同的網路環境了。
介面的程式碼如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvEnv = (TextView) findViewById(R.id.tv_env);
TextView tvChannel = (TextView) findViewById(R.id.tv_channel);
TextView tvPackage = (TextView) findViewById(R.id.tv_package);
String channel = WalleChannelReader.getChannel(this.getApplicationContext());
int envType = BuildConfig.ENV_TYPE;
String packageName = getPackageName();
switch (envType) {
case EnvType.DEVELOP:
tvEnv.setText("envType=" + "開發環境");
break;
case EnvType.CHECK:
tvEnv.setText("envType=" + "測試環境");
break;
case EnvType.PRODUCT:
tvEnv.setText("envType=" + "生產環境");
break;
}
tvChannel.setText("channel=" + channel);
tvPackage.setText("package=" + packageName);
}
}
3、打包多渠道
在Project的根目錄下新建channel檔案:
anzhi #安智
baidu #百度
huawei #華為
oppo #oppo
wdj #豌豆莢
xiaomi #小米
yyb #應用寶
執行gradle命令:
(1) 打包檔案內的渠道包
gradle assembleProductRelease -PchannelFile=channel
(2) 打包自定義陣列內的渠道包
gradle assembleProductRelease -PchannelList=qihu,vivo,lenovo
關於Walle庫的更多使用:詳見Github-walle
執行結果:17秒搞定8個包:1個預設包+7個渠道包
最後,奉上原始碼:WalleDemo
常見問題
1、找不到簽名檔案的配置?
汗,因為我的Demo中並沒有上傳我的jks檔案,你可以新增自己的jks檔案,然後在gradle.properties裡面配置好籤名檔案的密碼即可
在gradle.properties添加簽名檔案的配置key-value
在build.gradle中引用配置的key
2、develop、check、product,如果直接run程式碼,怎麼設定預設的環境?
點選檢視AndroidStudio左下角的BuildVariants,然後選擇設定預設的run環境即可。
BuildVariants= buildTypes* productFlavors
作者:天然魚
連結:https://www.jianshu.com/p/872dc6f89cb4
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。