我不是詩人,寫不出廈門的美;我不是歌手,唱不出廈門的情;我不是畫家,畫不出廈門的景。
我只是一名程序員,我只能用我的眼,我的心去看去感受,那久違的海風吹拂著臉頰,好似內心那一份煩躁與沉重也隨著海風飄向了遠方 . . . . . .
一、Gradle多渠道打包之緣由
時間要追溯到兩年前,當時我還在使用 eclipse
開發工具。兄弟事業部有款產品需要封包(使用webview打包成app),并提出了相關的需求:
針對不同商家地址(webview加載url),App名稱,應用圖標,歡迎頁背景,狀態欄顏色(背景同色)都不同,以及版本號不同。
針對不同的商家都必須打包成獨立的App,不會出現覆蓋安裝。
針對以上的需求每次打包都需要替換App名稱,應用圖標,背景等資源,還必須修改包名(帶來的一系列報錯)。后期又提出了升級功能,又得把資源、包名修改回去,一番折騰真的欲仙欲死。后來我干脆每次都新建項目打包,業務邏輯沒有變化只是資源發生了改變,代碼是拷貝了一份又一份,而且商家一多,維護起來真的是找得死去活來的,加之客戶提出新功能,我每個商家都需要擼一遍 . . . 神啊,誰來拯救我啊
二、自我拯救之路
在后來接觸到AndroidStudio
(簡稱AS),逐漸的轉到了AS
開發,確實比 eclipse
高效快速方便。 gradle
構建功能真心非常強大,默認有 debug ,release 版本,我們可以針對不同版本做不同配置,這不正好解決我所遇到的問題。gradle
提供了productFlavors
節點針對不同的版本做不同的配置。
比如有【四季易購】【仁仁家】【庫樂購】商家需要打包。
我在每個分支下面都重新配置applicationId
這個屬性,從而使打包出來的apk的包名不一樣,避免了覆蓋安裝。
當然針對不同的商家 App名稱,圖標不一樣。這個時候我們就需要配置manifestPlaceholders
屬性,manifestPlaceholders
是一個類似HashMap
的容器,因此在manifestPlaceholders
可以配置多個屬性。如下我們可以這樣配置:
gradle配置:
AndroidManifest配置:
注意:節點 meta-data 的配置。
${icon}
,${app_name}
引用 manifestPlaceholders
容器中 icon
, app_name
的值。
客戶的需求不僅僅更改App名稱與圖標,還需要修改webview
加載地址,歡迎頁背景圖片等等,具體配置如下圖:
注意:新增的配置同樣需要在清單文件中添加 meta-data
節點。
<meta-data
android:name="welcome_bg"
android:value="${welcome_bg}"/>
<meta-data
android:name="tint_color"
android:value="${tint_color}"/>
<meta-data
android:name="load_url"
android:value="${load_url}"/>
我們可以通過 Java 代碼獲取到 meta-data
節點下 android:value
的值。
一般在 MyApplication
獲取節點的值:
ApplicationInfo info = null;
try {
info = this.getPackageManager().getApplicationInfo(getPackageName(), PackageManager
.GET_META_DATA);
int tintColor = info.metaData.getInt("tint_color");
String loadUrl=info.metaData.getString("load_url");
String welcomePath = info.metaData.getString("welcome_bg");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
注意:設置welcome_bg:"@mipmap/klg_welcome"
,我這里以int welcomeRes = info.metaData.getInt("welcome_bg");
去取值,每次都返回0,但tint_color
的值就正常。按正常思維@mipmap/klg_welcome
返回的是 int
值,后來我換成getString
還真獲取到了值:res/mipmap-hdpi-v4/sjyg_welcome.png
。獲取到路徑值,背景的圖片資源就不能直接使用。
那么我們把路徑資源轉換成int
資源,這里就用到了 Java 的反射。具體代碼如下:
Class c = R.mipmap.class;
Field[] fields = c.getFields();
for (Field field : fields) {
if (field.getName().equals(welcomePath.substring(welcomePath.lastIndexOf("/") + 1,
welcomePath.lastIndexOf(".")))) {
this.welcomeBgRes = (int) field.get(c.newInstance());
break;
}
}
截取路徑字符串獲取圖片的【名稱】,根據【名稱】在【R.mipmap.class】類中查找,找到則返回該屬性的值。
這樣我們就把不同的配置信息保存到了MyApplication
中,使用的時候直接調用。
還有一種方式在Java代碼中可以方便獲取到gradle
配置文件的數據:
通過代碼:context.getResources().getString(R.string.key);
獲取值。
注意通過此方式 strings.xml
文件下不能有同名的 key
屬性。不然會報相同資源引用錯誤。
三、生成APK
如果你想生成所有渠道的包:
Terminal命令輸入如下指令:
gradlew assembleRelease
構建成功請在以下目錄查看:
如果你想針對某個渠道打包:
方式一:
配置不同渠道基礎信息。
方式二:
更改 applicationId
,添加 manifestPlaceholders
集合。
多渠道打包,并不需要更改百度、高德等第三方的key
。
多渠道打包,解決了以往深深的憂傷。