Chinaunix首页 | 论坛 | 博客
  • 博客访问: 156733
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 729
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-08 14:00
文章分类

全部博文(9)

文章存档

2015年(1)

2014年(2)

2013年(6)

分类: Android平台

2015-11-13 15:59:56

   在android项目中偶尔会出现依赖第三方库包,出现资源ID(packageId+typeId+ItemValue)发生冲突的问题(网上有很多解决方案,不一一列举,如public 限定等)。那么对于我们自己提供的库包,如果能指定其包的命令空间(默认是从127开始),特别考虑mutiDex的情况,自定义修改package ID显得意义重大。网上已经有很多修改package ID 的AAPT可执行文件(但是绝大部分不提供源码,觉得很神,就决定自己研究一下),通过命令行参数提供package ID赋值,现在从aapt资源打包源码流程角度,a.讲解该过程的中何时会生成应用程序包的package ID,b.然后如何进行修改。
    aapt首先根据命令行参数路径,寻找到androidmanifest文件,提取出应用程序的名称,创建resourceTable.
    具体调用路径main(main.cpp)-->handleCommand(command.cpp)->doPackage-->buildResources(Resource.cpp)

点击(此处)折叠或打开

  1. status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
  2. {
  3.     // First, look for a package file to parse. This is required to
  4.     // be able to generate the resource information.
  5.     sp<AaptGroup> androidManifestFile =
  6.             assets->getFiles().valueFor(String8("AndroidManifest.xml"));
  7.     if (androidManifestFile == NULL) {
  8.         fprintf(stderr, "ERROR: No AndroidManifest.xml file found.\n");
  9.         return UNKNOWN_ERROR;
  10.     }

  11.     status_t err = parsePackage(bundle, assets, androidManifestFile);
  12.     if (err != NO_ERROR) {
  13.         return err;
  14.     }

  15.     NOISY(printf("Creating resources for package %s\n",
  16.                  assets->getPackage().string()));

  17.     ResourceTable table(bundle, String16(assets->getPackage()));
  18.     err = table.addIncludedResources(bundle, assets);
        从第5行到第20行,我们需要关注的过程主要是读取androidManifest.xml内的应用名称(parsePackage比较麻烦,它会收集工程XML文件的元素<资源>信息,并对XML进行扁平压缩,最终写入到ResXMLTree的数据结构中),来创建一个资源表Resourcetable(资源打包最后阶段会根据该内容生成资源索引表resources.arsc),在上述代码第21行,我们能看到table.addIncludedResources(bundle, assets);该函数主要是用于添加被引用的资源包,当然一般是系统资源包android.jar.
      

点击(此处)折叠或打开

  1. status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
  2. {
  3.     status_t err = assets->buildIncludedResources(bundle);
  4.     if (err != NO_ERROR) {
  5.         return err;
  6.     }

  7.     // For future reference to included resources.
  8.     mAssets = assets;

  9.     const ResTable& incl = assets->getIncludedResources();

  10.     // Retrieve all the packages.
  11.     const size_t N = incl.getBasePackageCount();
  12.     for (size_t phase=0; phase<2; phase++) {
  13.         for (size_t i=0; i<N; i++) {
  14.             String16 name(incl.getBasePackageName(i));
  15.             uint32_t id = incl.getBasePackageId(i);
  16.             // First time through: only add base packages (id
  17.             // is not 0); second time through add the other
  18.             // packages.
  19.             if (phase != 0) {
  20.                 if (id != 0) {
  21.                     // Skip base packages -- already one.
  22.                     id = 0;
  23.                 } else {
  24.                     // Assign a dynamic id.
  25.                     id = mNextPackageId;
  26.                 }
  27.             } else if (id != 0) {
  28.                 if (id == 127) {
  29.                     if (mHaveAppPackage) {
  30.                         fprintf(stderr, "Included resources have two application packages!\n");
  31.                         return UNKNOWN_ERROR;
  32.                     }
  33.                     mHaveAppPackage = true;
  34.                 }
  35.                 if (mNextPackageId > id) {
  36.                     fprintf(stderr, "Included base package ID %d already in use!\n", id);
  37.                     return UNKNOWN_ERROR;
  38.                 }
  39.             }
  40.             if (id != 0) {
  41.                 NOISY(printf("Including package %s with ID=%d\n",
  42.                              String8(name).string(), id));
  43.                 sp<Package> p = new Package(name, id);
  44.                 mPackages.add(name, p);
  45.                 mOrderedPackages.add(p);

  46.                 if (id >= mNextPackageId) {
  47.                     mNextPackageId = id+1;
  48.                 }
  49.             }
  50.         }
  51.     }

  52.     // Every resource table always has one first entry, the bag attributes.
  53.     const SourcePos unknown(String8("????"), 0);
  54.     sp<Type> attr = getType(mAssetsPackage, String16("attr"), unknown);

  55.     return NO_ERROR;
  56. }
        从上述代码14行到第55行,描述了添加引用依赖包的过程,核心在第46-48行,以Pair的格式存入依赖包(注意ID为包命名空间8位二进制,系统层为1)。
        从第59行getType()开始就要进入到当前资源包ID的命名了,ResourceTable::getType()---》call ResourceTable::getPackages()

点击(此处)折叠或打开

  1. sp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
  2. {
  3.     sp<Package> p = mPackages.valueFor(package);
  4.     if (p == NULL) {
  5.         if (mBundle->getIsOverlayPackage()) {
  6.             p = new Package(package, 0x00);
  7.         } else if (mIsAppPackage) {
  8.             if (mHaveAppPackage) {
  9.                 fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n"
  10.                                 "Use -x to create extended resources.\n");
  11.                 return NULL;
  12.             }
  13.             mHaveAppPackage = true;
  14.             p = new Package(package, 127);
  15.         } else {
  16.             p = new Package(package, mNextPackageId);
  17.         }
  18.         //printf("*** NEW PACKAGE: \"%s\" id=%d\n",
  19.         // String8(package).string(), p->getAssignedId());
  20.         mPackages.add(package, p);
  21.         mOrderedPackages.add(p);
  22.         mNextPackageId++;
  23.     }
  24.     return p;
  25. }
    在这里我们应用程序的ID赋值在第14行,最终在第20行到21行完成对新包的加入,代码相对比较简单,不再进行赘述,至此,应用程序的包ID被赋值为0x7f(127).
    

        那么到了这里大家大概知道如何修改源码了,是不是只要把127换成一个其它数字就可以了呢,可以说确实是的。
我们只需要对bundle数据结构进行扩展,将ID-127换成从bundle读入的一个变量即可。




阅读(9716) | 评论(1) | 转发(0) |
0

上一篇:小结一下本人今年应届生找工作经历

下一篇:没有了

给主人留下些什么吧!~~

3372405522016-02-19 16:02:54

特地登陆给好评