
簡評:最熟悉的地方也會有大學(xué)問。
對于 Android 開發(fā)者來說,Package Name 應(yīng)當(dāng)再熟悉不過了,或許有些同學(xué)還注意到了 App 的 build.gradle 中有一個 applicationId,它的值通常都和包名一致,但其實(shí)二者是存在區(qū)別的。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.stylingandroid.packagename">
...
</manifest>
可以看到這里有一個包名:com.stylingandroid.packagename,而我們這里在 build.gradle 中為 applicationId 加上 .release 和 .debug 兩個不同的后綴:
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.stylingandroid.packagename"
minSdkVersion 23
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationIdSuffix ".release"
}
debug {
applicationIdSuffix ".debug"
}
}
}
我們比較打包出來兩個 APK 的 Manifest 文件,可以觀察下其中 package 的值:

可以發(fā)現(xiàn)應(yīng)用最終的包名其實(shí)是由 applicationId 決定的,而之前 Manifest 中的 package 值主要是做兩件事:
- 指明類的路徑。比如我們在 manifest 文件中聲明
<activity android:name=".MainActivity">,實(shí)際會被解析為com.stylingandroid.packagename.MainActivity - 指明 R.java 文件的路徑,對于本文的例子來說就是
com.stylingandroid.packagename.R
這些在官方文檔中都有講解,主要需要注意的是文檔的最后一段:
Although you may have a different name for the manifest package and the Gradle applicationId, the build tools copy the application ID into your APK’s final manifest file at the end of the build
注意文檔中所說的,Android 是在程序編譯的 最后 才將 application ID 拷貝進(jìn) APK 的 manifest 文件的。
如果你像上面那樣在 buildTypes 中修改了 applicationId 值,那么在代碼中想要獲取到應(yīng)用包名就需要注意,看看下面的代碼:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView packageNameTextView = (TextView) findViewById(R.id.package_name);
TextView applicationIdTextView = (TextView) findViewById(R.id.application_id);
packageNameTextView.setText(getString(R.string.package_name, BuildConfig.class.getPackage().toString()));
applicationIdTextView.setText(getString(R.string.application_id, BuildConfig.APPLICATION_ID));
}
}
結(jié)果分別為:
Package Name: package com.stylingandroid.packagenameApplication ID: com.stylingandroid.packagename.debug
那為什么 Android 要在編譯的最后才將 application ID 拷貝進(jìn) manifest 文件中呢?
理由很簡單,如果 BuildConfig.java 和 R.java 文件使用了 applicationId 而不是 package name,編譯的時候路徑會出錯。
日報延伸閱讀:
歡迎關(guān)注: