在android项目中,出现资源ID(packageId+typeId+ItemValue)发生冲突的问题。特别是插件化开发的需求背景时(网上有很多解决方案,不一一列举,如public 限定等)。那么对于我们自己提供的库包,如果能指定其包的命令空间(默认是从127开始),特别考虑mutiDex的情况,自定义修改package ID显得意义重大。网上已经有很多修改package ID 的AAPT可执行文件(但是绝大部分不提供源码,觉得很神,就决定自己研究一下),通过命令行参数提供package ID赋值,现在从aapt资源打包源码流程角度,讲解该过程中何时会生成应用程序包的package ID, 然后如何进行修改。
aapt首先根据命令行参数路径,寻找到androidmanifest文件,提取出应用程序的名称,创建resourceTable.具体调用路径 main(main.cpp)-->handleCommand(command.cpp)->doPackage-->buildResources(Resource.cpp)
- status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
- {
- // First, look for a package file to parse. This is required to
- // be able to generate the resource information.
- sp<AaptGroup> androidManifestFile =
- assets->getFiles().valueFor(String8("AndroidManifest.xml"));
- if (androidManifestFile == NULL) {
- fprintf(stderr, "ERROR: No AndroidManifest.xml file found.\n");
- return UNKNOWN_ERROR;
- }
-
- status_t err = parsePackage(bundle, assets, androidManifestFile);
- if (err != NO_ERROR) {
- return err;
- }
-
- NOISY(printf("Creating resources for package %s\n",
- assets->getPackage().string()));
-
- ResourceTable table(bundle, String16(assets->getPackage()));
- err = table.addIncludedResources(bundle, assets);
- status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
- {
- status_t err = assets->buildIncludedResources(bundle);
- if (err != NO_ERROR) {
- return err;
- }
-
- // For future reference to included resources.
- mAssets = assets;
-
- const ResTable& incl = assets->getIncludedResources();
-
- // Retrieve all the packages.
- const size_t N = incl.getBasePackageCount();
- for (size_t phase=0; phase<2; phase++) {
- for (size_t i=0; i<N; i++) {
- String16 name(incl.getBasePackageName(i));
- uint32_t id = incl.getBasePackageId(i);
- // First time through: only add base packages (id
- // is not 0); second time through add the other
- // packages.
- if (phase != 0) {
- if (id != 0) {
- // Skip base packages -- already one.
- id = 0;
- } else {
- // Assign a dynamic id.
- id = mNextPackageId;
- }
- } else if (id != 0) {
- if (id == 127) {
- if (mHaveAppPackage) {
- fprintf(stderr, "Included resources have two application packages!\n");
- return UNKNOWN_ERROR;
- }
- mHaveAppPackage = true;
- }
- if (mNextPackageId > id) {
- fprintf(stderr, "Included base package ID %d already in use!\n", id);
- return UNKNOWN_ERROR;
- }
- }
- if (id != 0) {
- NOISY(printf("Including package %s with ID=%d\n",
- String8(name).string(), id));
- sp<Package> p = new Package(name, id);
- mPackages.add(name, p);
- mOrderedPackages.add(p);
-
- if (id >= mNextPackageId) {
- mNextPackageId = id+1;
- }
- }
- }
- }
-
- // Every resource table always has one first entry, the bag attributes.
- const SourcePos unknown(String8("????"), 0);
- sp<Type> attr = getType(mAssetsPackage, String16("attr"), unknown);
-
- return NO_ERROR;
- }
从第59行getType()开始就要进入到当前资源包ID的命名了, ResourceTable : :getType()---》call ResourceTable::getPackages()
- sp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
- {
- sp<Package> p = mPackages.valueFor(package);
- if (p == NULL) {
- if (mBundle->getIsOverlayPackage()) {
- p = new Package(package, 0x00);
- } else if (mIsAppPackage) {
- if (mHaveAppPackage) {
- fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n"
- "Use -x to create extended resources.\n");
- return NULL;
- }
- mHaveAppPackage = true;
- p = new Package(package, 127);
- } else {
- p = new Package(package, mNextPackageId);
- }
- //printf("*** NEW PACKAGE: \"%s\" id=%d\n",
- // String8(package).string(), p->getAssignedId());
- mPackages.add(package, p);
- mOrderedPackages.add(p);
- mNextPackageId++;
- }
- return p;
- }
那么到了这里大家大概知道如何修改源码了,是不是只要把127换成一个其它数字就可以了呢,可以说确实是的。我们只需要对bundle数据结构进行扩展,将ID-127换成从bundle读入的一个变量即可。