Подтвердить что ты не робот

Как получить файл в активах с Android NDK

Я пытаюсь получить доступ к файлу изображения в папке с исходной информацией. Теперь я могу успешно найти папку с ресурсами и ее подкаталоги, в которых находится конкретный файл, который я ищу:

AAssetDir* assetDir = AAssetManager_openDir(asset_manager, "images");
const char* filename;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL)
{
   __android_log_print(ANDROID_LOG_DEBUG, "Debug", filename);
}

AAssetDir_close(assetDir);

Я также использую OSG. Я установил изображение как текстуру в свой шейдер со следующим кодом:

texture->setImage(osgDB::readImageFile(fileNameWithPath));

Но это имя файла должно содержать абсолютный путь, так как он не находится в том же каталоге. Однако я обнаружил, что не могу получить абсолютный путь для каталога ресурсов, поскольку он сжат вместе с APK.

Будучи тем, что я не могу получить доступ к абсолютному пути, каким другим способом я мог бы воспользоваться для получения изображения? Также следует отметить, что я хочу, чтобы файлы в папке с ресурсами были привязаны к SD-карте.

4b9b3361

Ответ 1

Вы можете прочитать изображение из актива с помощью AAssetManager_open и AAsset_read, но поскольку объект находится в apk, вы не можете получить имя пути к файлу - он также сжимается. Вы можете сохранить данные в файл и прочитать из этого файла позже, или вы можете напрямую обработать кусок, который вы получили из вашего файла активов, если позволяет OSG.

Из здесь:

AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
const char* filename = (const char*)NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
    AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
    char buf[BUFSIZ];
    int nb_read = 0;
    FILE* out = fopen(filename, "w");
    while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0)
        fwrite(buf, nb_read, 1, out);
    fclose(out);
    AAsset_close(asset);
}
AAssetDir_close(assetDir);

Ответ 2

Еще одна вещь, о которой стоит упомянуть, заключается в том, что андроид ограничивает размер активов, которые можно прочитать в момент времени, до 1 Мб. Если ваш файл больше, вам нужно разбить его на куски. Вот мое рабочее решение, которое загружает файл в куски в вектор символов:

AAssetManager * mgr = app->activity->assetManager; 
AAssetDir* assetDir = AAssetManager_openDir(mgr, "");

const char* filename;
std::vector<char> buffer;

while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) 
{
    //search for desired file
    if(!strcmp(filename, /* searched file name */)) 
    {
        AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);

        //holds size of searched file
        off64_t length = AAsset_getLength64(asset);
        //keeps track of remaining bytes to read
        off64_t remaining = AAsset_getRemainingLength64(asset);
        size_t Mb = 1000 *1024; // 1Mb is maximum chunk size for compressed assets
        size_t currChunk;
        buffer.reserve(length);

        //while we have still some data to read
        while (remaining != 0) 
        {
            //set proper size for our next chunk
            if(remaining >= Mb)
            {
                currChunk = Mb;
            }
            else
            {
                currChunk = remaining;
            }
            char chunk[currChunk];

            //read data chunk
            if(AAsset_read(asset, chunk, currChunk) > 0) // returns less than 0 on error
            {
                //and append it to our vector
                buffer.insert(buffer.end(),chunk, chunk + currChunk);
                remaining = AAsset_getRemainingLength64(asset);
            }
        }
        AAsset_close(asset);
    }

}