How To Get File In Assets From Android NDK

我与影子孤独终老i 提交于 2019-11-26 02:19:57

问题


I\'m trying to access an image file in the assets folder from the native side. Now I can successfully search through the assets folder and its subdirectories locating the particular file that I am looking for:

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);

I am also using OSG. I set the image as a texture to my shader with the following code:

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

But that file name must include the absolute path as well since it is not located in the same directory. However I found out that I cannot get the absolute path for the assets directory, being that it is compressed along with the APK.

Being that I can\'t access the absolute path, what other way could I use to get the image? Also to note, I do want to keep the files in the asset folder as appose to the sd card.


回答1:


You can read the image from asset with AAssetManager_open & AAsset_read, but since asset lies in apk you can't get a filepath name for it - it is also compressed there. You can save the data to a file and read from that file later or you can directly process the chunk you got from your asset file if OSG allows.

From here:

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:


One more thing worth mentioning is that android puts restriction on asset size that can be read at time, to 1Mb. In case your file is bigger than that, you have to split it into chunks. Here is my working solution which loads file in chunks to vector of chars:

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);
    }

}


来源:https://stackoverflow.com/questions/13317387/how-to-get-file-in-assets-from-android-ndk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!