利用 Android Studio 和 Gradle 打包多版本APK

在項目開發過程當中,常常會有須要打包不一樣版本的 APK 的需求。 好比 debug版,release版,dev版等等。 有時候不一樣的版本中使用到的不一樣的服務端api域名也不相同。 好比 debug_api.com,release_api.com,dev_api.com等等。java


不一樣的版本對應了不一樣的 api 域名,還可能對應不一樣的 icon 等。android


若是每次都在打包前修改咱們都手動來修改,這樣實在是不夠方便。api


但若是咱們使用了 Android Studio 和 Gradle,這個麻煩就能夠輕鬆省去。app


具體方式以下: 在 Android Studio 中打開 build.gradle(Module中)的 android 節點下添加以下代碼ide


buildTypes {工具


//這裏的名字自定義,不要求大小寫gradle

release{ui


// 這裏是在 applicationId 中添加了一個後綴。因此『.』要加上spa

applicationIdSuffix ".release"翻譯


// 這裏的做用是選擇是否混淆代碼

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}


dev{

applicationIdSuffix ".dev"

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'


}

}


// 這裏是爲了避免同過的版本設置一些特殊的參數,並不直接和 buildType 關聯。

//例如:使用 buildType 中的 dev 版本,也可使用 flavors_release 裏面設置的自定義參數。這須要本身按照需求制定。

productFlavors{


//自定義名字不過不能和上面buildType中相同,否則Gradle編譯會不經過。在這裏使用了『flavors_』前綴以便區分。

flavors_release{


// manifestPlaceholders中寫到的『str』,『package_name』不支持用大寫,不然Gradle編譯會不經過。

// 這裏所設置的變量能夠直接使用在『AndroidManifest.xml』中,使用方式爲:${package_name}

// android:label="${package_name}"

manifestPlaceholders = [str:"releaseStr",package_name:"com.sunhz.mvptest.release"]


// 這裏的參數是爲了在 java 代碼中使用,具體的使用方式爲:context.getResources().getString(R.string.strKey);

resValue("string" , "strKey","releaseStrValue")

}


flavors_dev{

manifestPlaceholders = [str:"devStr",package_name:"com.sunhz.mvptest.dev"]


resValue("string" , "strKey","devStrValue")

}

}


上面設置完成後,咱們要在哪裏使用它?


使用方式以下: 在 Android Studio 的工具欄中,找到『Build』項,找到『Generate Signed APK…』。


選擇 Module -> 建立 APK key,或者輸入 APK key密碼 -> 關鍵來了!以下圖。

0?wx_fmt=png


在『BuildType』處,選擇咱們在 build.gradle 中設置的兩個 BuildType,分別是releas,dev,debug。其中『debug』爲 Android Studio 自帶的。


在『Flavors』處,選擇咱們在 build.gradle 中設置的兩個Flavors,以方便直接使用定義在 build.gradle 中自定義的參數。


因此! 上面我有提到說,buildType 和 Flavors 並無直接的聯繫。 他們能夠根據用戶需求互相配合使用。如上圖,BuildType 選擇了 release,但 Flavors 選擇的倒是 flavors_dev。


到此基本的使用就所有說完了。


這裏有一個問題,打出來的不一樣版本的包,所有都可以在同一部手機上安裝,且可以將兩個包全都發布到 Google 的市場上去這是爲何呢?


這裏就要提到在 BuildType 中咱們所設置的『applicationIdSuffix』屬性了,按照這個屬性的字面翻譯爲:『applicationId 的後綴』,那這裏又來了一個問題,『applicationId』是什麼? 其實這個『applicationId』屬性,實際上在項目建立完成後就存在於 build.gradle 中。在 android 節點下的 defaultConfig 節點中。並且默認的 applicationId 和 AndroidManifest.xml 中的 package 屬性相同。


以下圖:

0?wx_fmt=png


咱們可以看到,這兩個屬性的默認值是相同的。


applicationId 和 packageName 它們是什麼關係?


默認建立項目後,二者相同。若是須要根據不一樣的需求構建不一樣版本的APK,這時咱們經過設置『applicationIdSuffix』能夠作到。


這裏有一個值得注意的現象。


舉個例子,咱們在打包時使用了 dev 類型,將打包出來的 APK 軟件安裝到手機中。


使用以下代碼,獲取咱們手機上全部程序的packageName。


PackageManager packageManager = mContext.getPackageManager();

List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);

List<String> packageNameList = new ArrayList<String>();

for (PackageInfo packageInfo : packageInfoList) {

packageNameList.add(packageInfo.packageName);

}


咱們打印出來的包名信息中,會出現 com.spencer_dev.test.dev 。並無出現 com.spencer_dev.test 。


可是! 若是經過反編譯工具,將 APK 包進行反編譯直接查看源代碼,在 java 代碼所在的 src 目錄中的包名,還和咱們設置的同樣,爲 com.spencer_dev.test 。可 AndroidManifest.xml 中的 package 和 BuildConfig 類中的 APPLICATION_ID 已經變成了 com.spencer_dev.test.dev 。


applicationId 和 packageName 它們各自表明什麼?


按照上面的結果來講, package 表明了 java 代碼中的包名。 applicationId 表明了應用中的惟一標識。和應用簽名一塊兒用來區別和其餘應用不一樣。我想這也就是爲何 Google 市場可以容許相同應用不一樣 applicationId 的緣由。

長按下方二維碼就能夠識別關注

0?wx_fmt=jpeg

相關文章
相關標籤/搜索