Android aapt实现资源分区(补充携程aapt源码)
2016-05-14 12:16
495 查看
大致内容看这篇文章Android中如何修改编译的资源ID值(默认值是0x7F…可以随意改成0x02~0x7E),但是该文章中修改并不完全,是有问题的,见后文细说。该文章也参考了携程的aapt源码。
从该文章中看到修改的地方主要有这么几个地方。
加入- -apk-module 参数读取外部packageId值。
根据Bundle把packageId传入,并进行传递。
设置packageId的时候判断Bundle中是否有packageId,有的话覆盖packageId。
下面的代码基于Android源码主分支,应该是6.0的源码。
第一点修改的地方就在Main.cpp中。增加参数,具体位置自己找。
其次要在Bundle.h中增加setApkModule和getApkModule方法,当然还有一个成员变量,加在什么位置自行找。
在ResourceTable.cpp中读取bundle中的mApkModule,如果不为空则覆盖packageId。
涉及到两个转换方法,其实现为。
可以看到
那么这个什么时候回执行到呢。就是当上面没有返回的情况下,前面返回的情况是当package为0x00,0x01,0x7f中的其中一个就会返回true,我们需要在else if分支加上我们的packageId的判断,让他返回true,但是这里没有Bundle,没办法传递packageId,因此我们需要一个辅助类Helper。
在/frameworks/base/include/androidfw/下新建Helper.h。这是一个单例。
在/frameworks/base/libs/androidfw/下新建Helper.cpp。对方法进行实现。
同时修改该目录中的Android.mk文件。加入该cpp。
回到ResourceTable.cpp中,在获取packageId后,将值传入到Helper单例中去。
再回到刚才扔出异常的那个地方,在else if中加入packageId的判断。
只是加了一个条件
再执行编译
这时候就能随意指定packageId了,范围在0x00~0x7f之间,其中0x00、0x01、0x7f已经被使用。
之前报错的原因也有可能6.0的源码发生了变化,也有可能携程开源的代码不全。这个结论也不好下。当然我也不敢保证我这么修改后一定没有问题。
从该文章中看到修改的地方主要有这么几个地方。
加入- -apk-module 参数读取外部packageId值。
根据Bundle把packageId传入,并进行传递。
设置packageId的时候判断Bundle中是否有packageId,有的话覆盖packageId。
下面的代码基于Android源码主分支,应该是6.0的源码。
第一点修改的地方就在Main.cpp中。增加参数,具体位置自己找。
else if(strcmp(cp, "-apk-module") == 0){ argc--; argv++; if (!argc) { fprintf(stderr, "ERROR: No argument supplied for '--apk-module' option\n"); wantUsage = true; goto bail; } bundle.setApkModule(argv[0]); }
其次要在Bundle.h中增加setApkModule和getApkModule方法,当然还有一个成员变量,加在什么位置自行找。
android::String8 mApkModule; const android::String8& getApkModule() const {return mApkModule;} void setApkModule(const char* str) { mApkModule=str;}
在ResourceTable.cpp中读取bundle中的mApkModule,如果不为空则覆盖packageId。
getApkModule().isEmpty()){ android::String8 apkmoduleVal=bundle->getApkModule(); packageId=apkStringToInt(apkmoduleVal); } " data-snippet-id="ext.bd5f786b6206cd2f893d03ed67ec3d0b" data-snippet-saved="false" data-codota-status="done">[code]//read the apk module if(!bundle->getApkModule().isEmpty()){ android::String8 apkmoduleVal=bundle->getApkModule(); packageId=apkStringToInt(apkmoduleVal); }
涉及到两个转换方法,其实现为。
'9') { return -1; } // Decimal or hex? if (s[i] == '0' && s[i+1] == 'x') { i += 2; bool error = false; while (i < len && !error) { val = (val*16) + apkgetHex(s[i], &error); i++; } if (error) { return -1; } } else { while (i < len) { if (s[i] < '0' || s[i] > '9') { return false; } val = (val*10) + s[i]-'0'; i++; } } if (i == len) { return val; } return -1; } uint32_t ResourceTable::apkgetHex(char c, bool* outError){ if (c >= '0' && c = 'a' && c = 'A' && c [code]bool ResTable::stringToValue(Res_value* outValue, String16* outString, const char16_t* s, size_t len, bool preserveSpaces, bool coerceType, uint32_t attrID, const String16* defType, const String16* defPackage, Accessor* accessor, void* accessorCookie, uint32_t attrType, bool enforcePrivate) const { //剩余代码 if (accessor) { uint32_t rid = accessor->getCustomResourceWithCreation(package, type, name, createIfNotFound); if (rid != 0) { if (kDebugTableNoisy) { ALOGI("Pckg %s:%s/%s: 0x%08x\n", String8(package).string(), String8(type).string(), String8(name).string(), rid); } uint32_t packageId = Res_GETPACKAGE(rid) + 1; if (packageId == 0x00) { outValue->data = rid; outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE; return true; } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) { // We accept packageId's generated as 0x01 in order to support // building the android system resources outValue->data = rid; return true; } } } } if (accessor != NULL) { accessor->reportError(accessorCookie, "No resource found that matches the given name"); } return false; //剩余代码 }
可以看到
reportError(accessorCookie, "No resource found that matches the given name"); }" data-snippet-id="ext.410e4ec0ea7a80b6c5085e09ea8a1eea" data-snippet-saved="false" data-codota-status="done">[code]if (accessor != NULL) { accessor->reportError(accessorCookie, "No resource found that matches the given name"); }
那么这个什么时候回执行到呢。就是当上面没有返回的情况下,前面返回的情况是当package为0x00,0x01,0x7f中的其中一个就会返回true,我们需要在else if分支加上我们的packageId的判断,让他返回true,但是这里没有Bundle,没办法传递packageId,因此我们需要一个辅助类Helper。
在/frameworks/base/include/androidfw/下新建Helper.h。这是一个单例。
#include #include #include #include #include #include using namespace std; class Helper { size_t packageId; public: static Helper* getInstance() { static Helper instance; return &instance; } size_t getPackageId(); void setPackageId(size_t _packageId); protected: struct Object_Creator { Object_Creator() { Helper::getInstance(); } }; static Object_Creator _object_creator; Helper() { packageId=0x7f; } ~Helper() { } }; #endif" data-snippet-id="ext.fe0442f9af16d9730060dc0bbd3dad6f" data-snippet-saved="false" data-codota-status="done">[code]#ifndef __Helper_h #define __Helper_h #include <stdio.h> #include <iostream> #include <string> #include <sstream> #include <fstream> #include <stdlib.h> #include <map> using namespace std; class Helper { size_t packageId; public: static Helper* getInstance() { static Helper instance; return &instance; } size_t getPackageId(); void setPackageId(size_t _packageId); protected: struct Object_Creator { Object_Creator() { Helper::getInstance(); } }; static Object_Creator _object_creator; Helper() { packageId=0x7f; } ~Helper() { } }; #endif
在/frameworks/base/libs/androidfw/下新建Helper.cpp。对方法进行实现。
#include #include using namespace std; Helper::Object_Creator Helper::_object_creator; size_t Helper::getPackageId(){ return packageId; } void Helper::setPackageId(size_t _packageId){ packageId=_packageId; }" data-snippet-id="ext.5bb895f9ddd2769ba015165c127a74a1" data-snippet-saved="false" data-codota-status="done">[code]#include <androidfw/Helper.h> #include <iostream> #include <string> using namespace std; Helper::Object_Creator Helper::_object_creator; size_t Helper::getPackageId(){ return packageId; } void Helper::setPackageId(size_t _packageId){ packageId=_packageId; }
同时修改该目录中的Android.mk文件。加入该cpp。
commonSources := \ 原来的内容 \ Helper.cpp
回到ResourceTable.cpp中,在获取packageId后,将值传入到Helper单例中去。
//read the apk module if(!bundle->getApkModule().isEmpty()){ android::String8 apkmoduleVal=bundle->getApkModule(); packageId=apkStringToInt(apkmoduleVal); } //set package id Helper::getInstance()->setPackageId(packageId);" data-snippet-id="ext.be93468fbd1b0c339edb50b9aa359ea5" data-snippet-saved="false" data-codota-status="done">[code]//引入头文件。 #include <androidfw/Helper.h> //read the apk module if(!bundle->getApkModule().isEmpty()){ android::String8 apkmoduleVal=bundle->getApkModule(); packageId=apkStringToInt(apkmoduleVal); } //set package id Helper::getInstance()->setPackageId(packageId);
再回到刚才扔出异常的那个地方,在else if中加入packageId的判断。
else if (packageId== Helper::getInstance()->getPackageId() ||packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) { // We accept packageId's generated as 0x01 in order to support // building the android system resources outValue->data = rid; return true; }" data-snippet-id="ext.a397c635ec159db754909c367922007a" data-snippet-saved="false" data-codota-status="done">[code]//引入头文件。 #include <androidfw/Helper.h> else if (packageId== Helper::getInstance()->getPackageId() ||packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) { // We accept packageId's generated as 0x01 in order to support // building the android system resources outValue->data = rid; return true; }
只是加了一个条件
packageId== Helper::getInstance()->getPackageId()
再执行编译
make aapt
这时候就能随意指定packageId了,范围在0x00~0x7f之间,其中0x00、0x01、0x7f已经被使用。
之前报错的原因也有可能6.0的源码发生了变化,也有可能携程开源的代码不全。这个结论也不好下。当然我也不敢保证我这么修改后一定没有问题。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories