Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Android NDK获取资产中的文件_Android_Android Ndk_Openscenegraph - Fatal编程技术网

如何从Android NDK获取资产中的文件

如何从Android NDK获取资产中的文件,android,android-ndk,openscenegraph,Android,Android Ndk,Openscenegraph,我正在尝试从本机端访问资产文件夹中的图像文件。现在,我可以成功搜索资产文件夹及其子目录,找到我要查找的特定文件: AAssetDir* assetDir = AAssetManager_openDir(asset_manager, "images"); const char* filename; while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) { __android_log_print(ANDROID_LOG

我正在尝试从本机端访问资产文件夹中的图像文件。现在,我可以成功搜索资产文件夹及其子目录,找到我要查找的特定文件:

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卡相对应。

您可以使用
AAssetManager\u open
&
AAsset\u read
,从资产中读取图像,但由于资产位于apk中,您无法获取它的文件路径名-它也在那里被压缩。您可以将数据保存到一个文件中,稍后再从该文件中读取,或者如果OSG允许,您可以直接处理从资产文件中获取的块

发件人:


还有一点值得一提的是,安卓对每次可读取的资产大小进行了限制,限制为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);
    }

}
AAssetManager*mgr=app->activity->assetManager;
AAssetDir*assetDir=AAssetManager_openDir(经理“”);
常量字符*文件名;
向量缓冲区;
而((filename=AAssetDir_getNextFileName(assetDir))!=NULL)
{
//搜索所需文件
如果(!strcmp(文件名,/*搜索文件名*/))
{
AAsset*asset=AAssetManager\u打开(管理器、文件名、AAsset\u模式\u流媒体);
//保存搜索文件的大小
off64\u t length=AAsset\u getLength64(资产);
//跟踪要读取的剩余字节
off64\u t剩余=AAsset\u getremaining64(资产);
size_t Mb=1000*1024;//1Mb是压缩资产的最大块大小
大小(单位);;
缓冲区(长度);
//虽然我们还有一些数据要读
而(剩余!=0)
{
//为下一块设置适当的大小
如果(剩余>=Mb)
{
currChunk=Mb;
}
其他的
{
currChunk=剩余;
}
字符块[currChunk];
//读取数据块
if(AAsset_read(asset,chunk,currChunk)>0)//错误时返回小于0
{
//并将其附加到我们的向量
insert(buffer.end(),chunk,chunk+currChunk);
剩余=AAsset_getremainingLength 64(资产);
}
}
AAsset_close(资产);
}
}

感谢您的快速响应。我会尝试一下,并在可能的时候给你更新。很抱歉更新太晚(忙了一周)。这很好用。其他应用程序通常是这样访问SD卡以外的文件的吗?@Robert不知道其他应用程序,但这看起来不错。请注意,使用此方法,您将在磁盘中提取APK的内容。根用户将能够访问应用程序的资产,因此请小心。osg没有从数据中读取图像的方法吗?您应该用AsSeMeMead加载数据,并从数据加载图像。@ USER 2591935,所有应用程序都可以访问资产。我不能理解——如何访问C++中的代码> AsSeTyMealsMeuth/Cuff>变量:ANDROIDAAP->活动-> AsSeTyMaungReN注。较小的数据块大小(如512 KB)如果完全适合缓存,则读取效率可能会更高。如果您正在读取整个文件,为什么不使用
AASSET\u MODE\u BUFFER
AASSET\u getBuffer()
如下所示:读取整个文件的概念很幼稚。分块,永远是最好的。但是我同意
AASSET\u MODE\u BUFFER
。@typelogic平台使用64Kbyte的块大小(截至今天的master)。此大小是一个实现细节,可能会因不同的Android版本或不同的设备而改变(OEM完全有能力调整其常数以更好地适应其硬件)。如果您使用
AASSET\u MODE\u BUFFER
getBuffer()
将比任何块都好,因为在引擎盖下,平台一次加载所有内容。我的实现类似。但是,对于android版本更新的设备(如10+),我的解决方案无法正常工作。现在我将切换到
AASSET\u MODE\u BUFFER
。安卓10上还有其他人有这样的问题吗+
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);
    }

}