前言:在讀完Android Gradle使用技巧-gradle使用詳細(xì)介紹后十厢,大家對(duì)Android Gradle已經(jīng)有了整體的了解贩据,接下來(lái)妓美,我們開(kāi)始詳細(xì)的了解gradle的每一個(gè)部分郑藏;
每個(gè) Android 應(yīng)用均有一個(gè)唯一的應(yīng)用 ID,像 Java 軟件包名稱一樣呵晚,例如 com.example.myapp蜘腌。此 ID 可以在設(shè)備上和 Google Play 商店中對(duì)您的應(yīng)用進(jìn)行唯一標(biāo)識(shí)。如果您要上傳新版本的應(yīng)用饵隙,應(yīng)用 ID(以及用于為其簽名的證書(shū))必須與原始 APK 相同撮珠。如果您更改了應(yīng)用 ID,Google Play 商店會(huì)將該 APK 視為完全不同的應(yīng)用癞季。因此劫瞳,發(fā)布您的應(yīng)用后,絕不應(yīng)更改應(yīng)用 ID绷柒。
您的應(yīng)用 ID 通過(guò)模塊的 build.gradle 文件中的 applicationId 屬性定義志于,如下所示:
android {
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
...
}
當(dāng)您在 Android Studio 中創(chuàng)建新項(xiàng)目時(shí),applicationId 與您在設(shè)置期間選擇的 Java 樣式軟件包名稱完全一致废睦。不過(guò)伺绽,除了這一點(diǎn),應(yīng)用 ID 和軟件包名稱彼此無(wú)關(guān)嗜湃。您可以更改代碼的軟件包名稱(代碼命名空間)奈应,這不會(huì)影響應(yīng)用 ID,反之亦然购披。不過(guò)杖挣,更改軟件包名稱會(huì)產(chǎn)生其他影響,您應(yīng)了解這一點(diǎn)刚陡,詳情參考下文惩妇;
雖然應(yīng)用 ID 看起來(lái)就像傳統(tǒng)的 Java 軟件包名稱一樣株汉,但應(yīng)用 ID 的命名規(guī)則限制性更強(qiáng)一些:
- 必須至少包含兩段(一個(gè)或多個(gè)圓點(diǎn))。
- 每段必須以字母開(kāi)頭歌殃。
- 所有字符必須為字母乔妈、數(shù)字或下劃線 [a-zA-Z0-9_]。
注意:應(yīng)用 ID 過(guò)去直接關(guān)聯(lián)到代碼的軟件包名稱氓皱;所以路召,有些 Android API 會(huì)在其方法名稱和參數(shù)名稱中使用“package name”一詞,但這實(shí)際上是您的應(yīng)用 ID波材。例如股淡,Context.getPackageName() 方法會(huì)返回您的應(yīng)用 ID。無(wú)論何時(shí)都不需要在應(yīng)用代碼以外分享代碼的真實(shí)軟件包名稱各聘。
更改用于構(gòu)建變體的應(yīng)用 ID
當(dāng)您為應(yīng)用構(gòu)建 APK 時(shí)揣非,構(gòu)建工具會(huì)使用 build.gradle 文件的 defaultConfig 塊中定義的應(yīng)用 ID 標(biāo)記 APK(如下所示)。不過(guò)躲因,如果您要?jiǎng)?chuàng)建不同版本的應(yīng)用,讓其在 Google Play 商店中顯示為單獨(dú)的詳情(如“free”和“pro”版本)忌傻,則需要?jiǎng)?chuàng)建單獨(dú)的構(gòu)建變體大脉,這些變體各自具有不同的應(yīng)用 ID。
在這種情況下水孩,每個(gè)構(gòu)建變體應(yīng)定義為單獨(dú)的產(chǎn)品變種镰矿。對(duì)于 productFlavors 塊中的每個(gè)變種,您可以重新定義 applicationId 屬性俘种,也可以使用 applicationIdSuffix 在默認(rèn)的應(yīng)用 ID 上追加一段秤标,如下所示:
android {
defaultConfig {
applicationId "com.example.myapp"
}
productFlavors {
free {
applicationIdSuffix ".free"
}
pro {
applicationIdSuffix ".pro"
}
}
}
這樣,“free”產(chǎn)品變種的應(yīng)用 ID 就是“com.example.myapp.free”宙刘。
您也可以根據(jù)自己的構(gòu)建類型使用 applicationIdSuffix 追加一段苍姜,如下所示:
android {
...
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
}
由于 Gradle 會(huì)在產(chǎn)品變種后面應(yīng)用構(gòu)建類型配置,因此“free debug”構(gòu)建變體的應(yīng)用 ID 現(xiàn)在是“com.example.myapp.free.debug”悬包。如果您希望同一設(shè)備上同時(shí)具有調(diào)試版本和發(fā)布版本衙猪,這會(huì)很有用,因?yàn)閮蓚€(gè) APK 不能具有相同的應(yīng)用 ID布近。
注意:為了與以前的 SDK 工具兼容垫释,如果您未在 build.gradle 文件中定義 applicationId 屬性,構(gòu)建工具會(huì)將 AndroidManifest.xml 文件中的軟件包名稱用作應(yīng)用 ID撑瞧。在這種情況下棵譬,重構(gòu)您的軟件包名稱也會(huì)更改您的應(yīng)用 ID
將構(gòu)建變量注入清單
如果您需要將變量插入在 build.gradle 文件中定義的 AndroidManifest.xml 文件,則可以使用 manifestPlaceholders 屬性來(lái)執(zhí)行此操作预伺。此屬性采用鍵值對(duì)的映射订咸,如下所示:
android {
defaultConfig {
manifestPlaceholders = [hostName:"www.example.com"]
}
...
}
然后琅束,您可以將某個(gè)占位符作為屬性值插入清單文件,如下所示:
<intent-filter ... >
<data android:scheme="http" android:host="${hostName}" ... />
...
</intent-filter>
默認(rèn)情況下算谈,構(gòu)建工具還會(huì)在 ${applicationId} 占位符中提供應(yīng)用的應(yīng)用 ID涩禀。該值始終與當(dāng)前編譯的最終應(yīng)用 ID(包括編譯變體的應(yīng)用 ID 更改)一致。當(dāng)您要對(duì)標(biāo)識(shí)符(如 intent 操作)使用唯一的命名空間時(shí)然眼,這很有用艾船,即使要求在編譯變體之間保持唯一性,這也很有用高每。
例如屿岂,如果您的 build.gradle 文件如下所示:
android {
defaultConfig {
applicationId "com.example.myapp"
}
productFlavors {
free {
applicationIdSuffix ".free"
}
pro {
applicationIdSuffix ".pro"
}
}
}
那么,您可以按如下方式將應(yīng)用 ID 插入清單:
<intent-filter ... >
<action android:name="${applicationId}.TRANSMOGRIFY" />
...
</intent-filter>
當(dāng)您構(gòu)建“free”產(chǎn)品變種時(shí)鲸匿,清單結(jié)果如下所示:
<intent-filter ... >
<action android:name="com.example.myapp.free.TRANSMOGRIFY" />
...
</intent-filter>
更改軟件包名稱
默認(rèn)情況下爷怀,項(xiàng)目的軟件包名稱與應(yīng)用 ID 匹配,但您可以更改軟件包名稱带欢。不過(guò)运授,如果您要更改軟件包名稱,需要注意的是乔煞,軟件包名稱(由項(xiàng)目目錄結(jié)構(gòu)定義)應(yīng)始終與 AndroidManifest.xml 文件中的 package 屬性匹配吁朦,如下所示
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp"
android:versionCode="1"
android:versionName="1.0" >
Android 構(gòu)建工具使用 package 屬性來(lái)發(fā)揮兩種作用:
- 它將此名稱用作應(yīng)用生成的 R.java 類的命名空間。
示例:對(duì)于上面的清單渡贾,R 類將為 com.example.myapp.R逗宜。
- 它會(huì)使用此名稱解析清單文件中聲明的任何相關(guān)類名。
示例:對(duì)于上面的清單空骚,聲明為 <activity android:name=".MainActivity"> 的 Activity 將解析為 com.example.myapp.MainActivity纺讲。
因此,package 屬性中的名稱應(yīng)始終與項(xiàng)目的基礎(chǔ)軟件包名稱匹配囤屹,基礎(chǔ)軟件包中保存著您的 Activity 及其他應(yīng)用代碼熬甚。當(dāng)然,您的項(xiàng)目中可以包含子軟件包牺丙,但是這些文件必須從 package 屬性導(dǎo)入使用命名空間的 R.java 類则涯,而且清單中聲明的任何應(yīng)用組件都必須添加缺失的子軟件包名稱。
如果您要完全重構(gòu)您的軟件包名稱冲簿,請(qǐng)確保也更新 package 屬性粟判。只要您使用 Android Studio 的工具重命名和重構(gòu)您的軟件包,那么這些屬性就會(huì)自動(dòng)保持同步峦剔。(如果它們未保持同步档礁,您的應(yīng)用代碼將無(wú)法解析 R 類,因?yàn)樗辉傥挥谕卉浖辛吣⑶仪鍐螣o(wú)法識(shí)別您的 Activity 或其他組件呻澜。)
注意:您必須始終在項(xiàng)目的主 AndroidManifest.xml 文件中指定 package 屬性递礼。如果您有其他清單文件(如產(chǎn)品變種或構(gòu)建類型的清單文件),請(qǐng)注意羹幸,優(yōu)先級(jí)最高的清單文件提供的軟件包名稱始終用于最終合并的清單脊髓。
還有一點(diǎn)需要了解:雖然清單 package 和 Gradle applicationId 可以具有不同的名稱,但構(gòu)建工具會(huì)在構(gòu)建結(jié)束時(shí)將應(yīng)用 ID 復(fù)制到 APK 的最終清單文件中栅受。所以将硝,如果您在構(gòu)建后檢查 AndroidManifest.xml 文件,發(fā)現(xiàn) package 屬性發(fā)生更改就不足為奇了屏镊。實(shí)際上依疼,Google Play 商店和 Android 平臺(tái)會(huì)查看 package 屬性來(lái)識(shí)別您的應(yīng)用。所以而芥,構(gòu)建系統(tǒng)利用原始值(設(shè)置 R 類的命名空間并解析清單類名稱)后律罢,它會(huì)舍棄該值并將其替換為應(yīng)用 ID。