android 资源如何查找(AaptAssets)分析

AaptAsset.cpp 位于 src/frameworks/base/tools/aapt目录xiam
主要入手是从 函数 ssize_t AaptAssets::slurpFromArgs(Bundle* bundle)开始
首先先判断 是否存在 AndroidManifest.xml 这个文件,然后加入,
在加入文件的时候,使用到 status_t AaptGroup::addFile(const sp& file) 此函数
status_t AaptGroup::addFile(const sp& 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 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 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 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 ..
..
..
用到了 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 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& 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包查看
Tags: 

延伸阅读

最新评论

发表评论