您的位置:首页 > 移动开发 > Android开发

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中。增加参数,具体位置自己找。

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的源码发生了变化,也有可能携程开源的代码不全。这个结论也不好下。当然我也不敢保证我这么修改后一定没有问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息