简评:最熟悉的地方也会有大学问。

对于 Android 开发者来说,Package Name 应当再熟悉不过了,或许有些同学还注意到了 App 的 build.gradle 中有一个 applicationId,它的值通常都和包名一致,但其实二者是存在区别的。

<?xml version="1.0" encoding="utf-8"?>   ...

可以看到这里有一个包名: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 文件中声明,实际会被解析为 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 导读三篇优质英文文章。
  • 网易云电台「极光日报**」,上下班路上为你读报。

更多相关文章

  1. Android(安卓)内部存储安装apk文件实现
  2. 【原创】The Error in Android(安卓)developing
  3. Android(安卓)模拟器运行编译后的源码
  4. Android(安卓)webview最简单小例子
  5. Android(安卓)Camera HAL浅析
  6. 在Android(安卓)Studio中使用Android-PullToRefresh Library
  7. android 简单试题系统
  8. Android(安卓)5.0 如何正确启用isLoggable(二)__原理分析
  9. Mac 打 Android(安卓)包遇到 open too many files 解决办法

随机推荐

  1. 坑爹的Android新ADT
  2. androidの实现分享功能
  3. Android常见问题(一点一点总结未完成)
  4. android中MotionEvent.ACTION_CANCEL事件
  5. android aapt使用小结
  6. Android访问Servlet
  7. Android3.0自带天气例子
  8. MySQL处理JSON常见函数的使用
  9. MySQL和Python交互的示例
  10. mysql字符集相关总结