web-dev-qa-db-ja.com

アセットのファイルを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カードへの提案として、資産フォルダにファイルを保持したいと思います。

24
Robert

AAssetManager_openAAsset_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);
30
auselen

言及する価値のあるもう1つのことは、Androidは、一度に読み取ることができるアセットサイズを1Mbに制限します。ファイルがそれより大きい場合は、チャンクに分割する必要があります。チャンクのファイルを文字のベクトルにロードする私の作業ソリューションです:

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

}
0
wlochaty