Android MediaScanner.cpp 源代码解析

1. 简介

实现对文件夹的递归扫描
libmedia – libmedia.so
frameworks\av\media\libmedia\MediaScanner.cpp
Android MediaScanner.cpp 源代码解析_第1张图片

2. 对文件的扫描

由JNI调用processDirectory,然后由doProcessDirectory和doProcessDirectoryEntry实现对文件夹的递归扫描。

2.1 doProcessDirectory

循环扫描该文件夹内的所有项

MediaScanResult MediaScanner::doProcessDirectory(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
    char* fileSpot = path + strlen(path);
    struct dirent* entry;
    .....
    // Treat all files as non-media in directories that contain a ".nomedia" file
    .....
    //Skip .nomedia file

    DIR* dir = opendir(path);

    MediaScanResult result = MEDIA_SCAN_RESULT_OK;
    while ((entry = readdir(dir))) {
        if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
                == MEDIA_SCAN_RESULT_ERROR) {
            result = MEDIA_SCAN_RESULT_ERROR;
            break;
        }
    }
    closedir(dir);
    return result;
}

2.2 doProcessDirectoryEntry

判断该项目是文件、文件夹还是需要跳过的项。
if 文件夹
doProcessDirectory
else if 文件
通过JNI调用java层scanFile
else if skip
skip this file or folder

MediaScanResult MediaScanner::doProcessDirectoryEntry(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
        struct dirent* entry, char* fileSpot) {
    struct stat statbuf;
    const char* name = entry->d_name;
    ........
    int type = entry->d_type;
    if (type == DT_UNKNOWN) {
        if (stat(path, &statbuf) == 0) {
            if (S_ISREG(statbuf.st_mode)) {
            //文件
                type = DT_REG;
            } else if (S_ISDIR(statbuf.st_mode)) {
            //文件夹
                type = DT_DIR;
            }
        }
    }
    if (type == DT_DIR) {
        bool childNoMedia = noMedia;
        // set noMedia flag on directories with a name that starts with '.'
        // for example, the Mac ".Trashes" directory
        if (name[0] == '.')
            childNoMedia = true;

        // report the directory to the client
        if (stat(path, &statbuf) == 0) {
            status_t status = client.scanFile(path, statbuf.st_mtime, 0,
                    true /*isDirectory*/, childNoMedia);
            if (status) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
        }

        // and now process its contents
        strcat(fileSpot, "/");
        MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
                client, childNoMedia);
        if (result == MEDIA_SCAN_RESULT_ERROR) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    } else if (type == DT_REG) {
        stat(path, &statbuf);
        status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
                false /*isDirectory*/, noMedia);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    return MEDIA_SCAN_RESULT_OK;
}

你可能感兴趣的:(android,源代码,MediaScan)