AaptAsset.cpp 位于 src/frameworks/base/tools/aapt目录xiam
主要入手是从 函数 ssize_t AaptAssets::slurpFromArgs(Bundle* bundle)开始
首先先判断 是否存在 AndroidManifest.xml 这个文件,然后加入,
在加入文件的时候,使用到 status_t AaptGroup::addFile(const sp<AaptFile>& file) 此函数
status_t AaptGroup::addFile(const sp<AaptFile>& file)
{
if (mFiles.indexOfKey(file->getGroupEntry()) < 0) {
file->mPath = mPath;
mFiles.add(file->getGroupEntry(), file);
return NO_ERROR;
}
SourcePos(file->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
getPrintableSource().string());
return UNKNOWN_ERROR;
}
变量mFiles是存放文件用的,
然后是遍历 assets文件夹,用到函数
ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
const AaptGroupEntry& kind, const String8& resType)
{
Vector<String8> fileNames;
{
DIR* dir = NULL;
dir = opendir(srcDir.string());
if (dir == NULL) {
fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno));
return UNKNOWN_ERROR;
}
/*
* Slurp the filenames out of the directory.
*/
/ /dirent含有指针,所以这while 相当于找到当前文件夹下面的第一级的 文件夹
while (1) {
struct dirent* entry;
entry = readdir(dir);
if (entry == NULL)
break;
if (isHidden(srcDir.string(), entry->d_name))
continue;
fileNames.add(String8(entry->d_name));
}
closedir(dir);
}
ssize_t count = 0;
/*
* Stash away the files and recursively descend into subdirectories.
*/
//通过找到的文件夹,然后调用 slurpFullTree 继续遍历
const size_t N = fileNames.size();
size_t i;
for (i = 0; i < N; i++) {
String8 pathName(srcDir);
FileType type;
pathName.appendPath(fileNames[i].string());
type = getFileType(pathName.string());
if (type == kFileTypeDirectory) {
sp<AaptDir> subdir;
bool notAdded = false;
//在保存文件夹的变量 mDirs里面判断是否已经存在这个文件夹
if (mDirs.indexOfKey(fileNames[i]) >= 0) {
subdir = mDirs.valueFor(fileNames[i]);
} else {
subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i]));
notAdded = true;
}
ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
resType);
if (res < NO_ERROR) {
return res;
}
if (res > 0 && notAdded) {
mDirs.add(fileNames[i], subdir);
}
count += res;
}
//如果不是文件夹,那就按文件存储
else if (type == kFileTypeRegular) {
sp<AaptFile> file = new AaptFile(pathName, kind, resType);
status_t err = addLeafFile(fileNames[i], file);
if (err != NO_ERROR) {
return err;
}
count++;
} else {
if (bundle->getVerbose())
printf(" (ignoring non-file/dir '%s')\n", pathName.string());
}
}
return count;
}
然后是查找遍历res文件夹
/*
* If a directory of resource-specific assets was supplied, slurp 'em up.
*/
for (size_t i=0; i<dirCount; i++) {
..
..
..
用到了 slurpResourceTree 这个函数
在 slurpResourceTree里面用到了
AaptGroupEntry::initFromDirName(const char* dir, String8* resType)这个函数
initFromDirName函数里面判断文件夹是否合法啊之类的 ,当然如果合法的话进行赋值之类的。
从这个函数里面调用的子函数里面可以看到,例如 因为分辨率或者屏幕是否touch、是否land等文件夹的命名规则
写这个笔记主要是因为在做系统的时候,考虑到不同客户需要使用到不同的参数
所以可以使用不同的文件夹
比如客户abc,那我们可以使用一个名字为 value-abc的文件
然后如果这个文件夹里面存在文件,比如 string.xml,那可以value-abc里面的string.xml去替换原来的value里面的string.xml,
if(file->getGroupEntry().overlay){
// printf("--fail-%s",file->getPrintableSource().string());
// printf(" %s\n", getPath().string());
String8 fileName = file->getSourceFile().getPathLeaf();
String8 pathName = file->getSourceFile().getPathDir();
const size_t N=mFiles.size();
size_t i;
for (i=0; i<N; i++) {
sp<AaptFile> file0 = mFiles.valueAt(i);
String8 name =file0->getSourceFile().getPathLeaf();
String8 path =file0->getSourceFile().getPathDir();
path.append("-");
path.append(kCustomer);
if( name == fileName && path == pathName ){
// printf("---john-- \n replace %s: %s \n",
// file0->getSourceFile().string(), file->getSourceFile().string());
// mFiles.replaceValueAt(i,new AaptFile());
sp<AaptFile>& aptFile= mFiles.editValueAt(i);
aptFile->mSourceFile = file->getSourceFile();
}
}
return NO_ERROR;
}else{
String8 name =file->getSourceFile().getPathLeaf();
String8 path =file->getSourceFile().getPathDir();
path.append("-");
path.append(kCustomer);
String8 cur_path = getPrintableSource();
if(path == cur_path.getPathDir() && name == cur_path.getPathLeaf()){
return NO_ERROR;
}
}
其中 overlay是自己添加的一个变量,在initFromDirName 里面,添加了自己的代码,判断所谓的 value-abc是否存在,如果存在 overlay置为true
其实apk文件存放资源的路径、结构跟pc上的类似 可以通过解压apk包查看