Android程序编译时更改包名

Android项目开发中有时候需要改动apk的包名,比如希望能同时安装测试/debug版本和正式版。比较容易的方法是在eclipse中右键点击项目,选择Android Tools->Rename Application Package。但是这样做比较麻烦,实际上我们也可以通过build脚本在打包时修改包名,方法如下。

  1. ant, 在build.xml中加入下面一段
<target name="-package-resources" depends="-crunch">
        <!-- only package resources if *not* a library project -->
        <do-only-if-not-library elseText="Library project: do not package resources..." >
            <aapt executable="${aapt}"
                    command="package"
                    manifestpackage="your pakcage name"
                    versioncode="${version.code}"
                    versionname="${version.name}"
                    debug="${build.is.packaging.debug}"
                    manifest="${out.manifest.abs.file}"
                    assets="${asset.absolute.dir}"
                    androidjar="${project.target.android.jar}"
                    apkfolder="${out.absolute.dir}"
                    nocrunch="${build.packaging.nocrunch}"
                    resourcefilename="${resource.package.file.name}"
                    resourcefilter="${aapt.resource.filter}"
                    libraryResFolderPathRefid="project.library.res.folder.path"
                    libraryPackagesRefid="project.library.packages"
                    libraryRFileRefid="project.library.bin.r.file.path"
                    previousBuildType="${build.last.target}"
                    buildType="${build.target}"
                    ignoreAssets="${aapt.ignore.assets}">
                <res path="${out.res.absolute.dir}" />
                <res path="${resource.absolute.dir}" />
                <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
                <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
            </aapt>
        </do-only-if-not-library>
    </target>

2. maven,在maven的build插件中加入下面一句

<plugin>
    <groupId>com.jayway.maven.plugins.android.generation2</groupId>
    <artifactId>android-maven-plugin</artifactId>
    <version>3.6.0</version>
    ...
    <configuration>
        ...
        <renameManifestPackage>com.napa.bluelion.reading.xzhz</renameManifestPackage>
        ....
    </configuration>
    ...
</plugin>

 3.   gradle, gradle已经考虑了我们这点需求,可以直接为测试和正式版打出两个不同包名的Apk

       可以直接在android default config中指定包名

       

android {
    compileSdkVersion 15

    defaultConfig {
        ...
        packageName: your package name
        testPackageName: your test package name
    }
}

也可以指定不同的productFlavors

android {
    ...

    defaultConfig {
        minSdkVersion 8
        versionCode 3001
    }

    productFlavors {
        flavor1 {
            versionCode 3001
            packageName: your packageName0
        }

        flavor2 {
            minSdkVersion 2500
            packageName: your package name1
        }
    }
}

注意事项。有时我们会在代码中通过如下方式动态获取资源文件的id来加载资源文件。

int resId = getResources().getIdentifier(resName, "drawable", getPackageName());

 这里的getPackageName会在编辑java代码时被编辑成Manifest文件中指定的package名字,导致我们在打包是改了包名以后出现运行时错误,找不到对应的资源文件。这时我们需要通过下面的方式在运行时动态获取pacakge name。

String packageName = getResources().getResourcePackageName(R.string.app_name);//这里的R.string.app_name是一个已经存在的资源。

int resId = getResources().getIdentifier(resName, "drawable", packageName);

原理:应用的包名其实不同于java代码的package名字。他实际上是appt工具在把资源文件编译成二进制时候用来生成资源的唯一标识用的。aapt在打包资源的时候会读取manifest文件中的包名来生成资源标识。所以以上的修改方式也就是通过在编译打包时指定package名字实现的。

相关推荐