Android Package Name vs. Application ID

簡評:最熟悉的地方也會有大學問。

對於 Android 開發者來說,Package Name 應當再熟悉不過了,或許有些同學還注意到了 App 的 build.gradle 中有一個 applicationId,它的值通常都和包名一致,但其實二者是存在區別的。

<?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 的值:

可以發現應用最終的包名其實是由 applicationId 決定的,而之前 Manifest 中的 package 值主要是做兩件事:

  • 指明類的路徑。比如我們在 manifest 文件中聲明 <activity android:name=".MainActivity">,實際會被解析為 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 拷貝進 APK 的 manifest 文件的。

如果你像上面那樣在 buildTypes 中修改了 applicationId 值,那麼在代碼中想要獲取到應用包名就需要注意,看看下面的代碼:

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)); }}

結果分別為:

Package Name: package com.stylingandroid.packagename

Application ID: com.stylingandroid.packagename.debug

那為什麼 Android 要在編譯的最後才將 application ID 拷貝進 manifest 文件中呢?

理由很簡單,如果 BuildConfig.java 和 R.java 文件使用了 applicationId 而不是 package name,編譯的時候路徑會出錯。

原文:Package Name vs. Application ID

擴展閱讀:

  • Android 開發工具推薦

  • 2017 年你應該嘗試的 25 個 Android 庫

歡迎關註:知乎專欄「極光日報」,每天為 Makers 導讀三篇優質英文文章。


推薦閱讀:

百人刷題狂歡周,七題連刷 20161124
如何看待phodal新書 《全棧應用開發-精益實踐》?

TAG:Android开发 | 编程 | 程序员 |