zoukankan      html  css  js  c++  java
  • android 资源如何查找(AaptAssets)分析

    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包查看

  • 相关阅读:
    OPC客户端的进程安全初始化
    [精华] Oracle安装(linux)总结一下[转]
    Linux防火墙iptables的设置与启动[转]
    Linux Server 5.5安装SVN+Apache服务[转]
    Red hat Linux Enterprise 5.4 Edtion 学习笔记[二]
    RedHat Linux 5企业版开启VNCSERVER远程桌面功能[转]
    Linux服务配置:Vsftp的基本配置[转]
    Linux查看和剔除当前登录用户
    Ubuntu10.04的中文问题汇集与解决[转]
    Linux下扩展swap分区的方法
  • 原文地址:https://www.cnblogs.com/rollrock/p/2107703.html
Copyright © 2011-2022 走看看