Android应用开发中的进程名,包名,applicationId

包名是安卓应用apk的唯一标识,安卓系统管理应用时,也是以包名索引。包名在AndroidManifest.xml中定义。在一个安卓应用程序工程创建之初,包名就已经确定。包名更多的是一个编译时概念。由android IDE自动生成的类,比如R、BuildConfig,都是以AndroidManifest.xml中定义的包名来构造类名,譬如,包名为“com.android.helloworld”,对应生成“com.android.helloworld.R”“com.android.helloworld.BuildConfig”。在需要使用的类中,需要imort,import语句也将保留在源代码中。

android应用在被启动时,对应的进程的进程名一般就是包名。android应用一般是运行在自己的进程中,除非通过AndroidManifest.xml中application定义中通过android:process字段指定运行在其他进程中(这种机制有特殊限定条件)。

applicationId是Android Studio提供的一种新的机制,可以在app/build.gradle中定义,譬如:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.android.helloworld"
        minSdkVersion 21
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}

Android Studio默认生成的app/build.gradle中,applicationId与AndroidManifest.xml中定义的包名一致。但显然,这两个值是可以独立设置的,可以不同。注意,在修改applicationId后,前面提到的IDE自动生成的类(譬如R、BuildConfig),包名不会被更新,仍然是AndroidManifest.xml中定义的包名,使用他们的类中的import语句也不需要更改。

但在修改applicationId之后,查看运行时进程名,会变成新的applicationId。在程序内运行时调用Context.getPackageName(),得到的仍然是新的applicationId。怀疑实现方式是build过程中,擦除并更新了AndroidManifest.xml中的package字段。使用apktool对编译生成的apk反编译,查看AndroidManifest.xml,发现确实是修改成了applicationId的值,验证了上述假设。

如上分析,对于applicationId的理解已经清晰。对于一个大的工程,修改包名的成本过高,几乎不可取。而经常会出现一个工程需要出不同版本,譬如收费版和免费版。这样就可以通过简单修改app/build.gradle中的applicationId来改变最终apk的包名,这样对于安卓手机来说,就是不同的app;同时,又不影响到开发编译时的代码一致性。

最后,说一个这种机制的坑。对于上文提到的自动生成的Java类(譬如R、BuildConfig),如果不是通过正常的import,而是通过在运行时调用Context.getPackageName()得到包名拼接成类名再用反射获取类,这样就会遇到ClassNotFoundException。需注意尽量不要用这种方式。反射虽然能让人体会到超越Java数据封装规则之上的快感,但是也有各种暗礁等着。




你可能感兴趣的:(Android应用开发中的进程名,包名,applicationId)