Как получить файл в активах с 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-карте.
Ответы
Ответ 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);
}
}