Android GameActivity(NativeActivity)读写文件
最近研究native android相关内容,其中最棘手的就是文件读写问题,最主要的是相关的文档很少。这里写下我所知道的方法。
由于本人使用的是Android14[arm64-v8a]版本的设备,能访问的路径相当有限,如果想要访问更多的路径,就不得不申请权限了。可用的路径如下:
1. assets:/assets
2. internalDataPath: /data/user/0/com.example.org/files
3. externalDataPath:/storage/emulated/0/Android/data/com.example.org/files
4. obbPath:/storage/emulated/0/Android/obb/com.example.org
5. Document:/storage/emulated/0/Document
6. Download:/storage/emulated/0/Download
一、Apk中的assets目录
以下列android工程为例,将资源文件放置在assets目录下,android studio打包时会将文件打包到apk中。
std::vector<char> ReadFromAssets(const char *path,android_app* app) {
if(app==nullptr) return {};
AAsset* file = AAssetManager_open(app->activity->assetManager,
path,AASSET_MODE_BUFFER);
if(file==nullptr) return {};
size_t len = AAsset_getLength(file);
std::vector<char> data;
data.resize(len);
AAsset_read(file, data.data(), len);
AAsset_close(file);
return data;
}
example:
dir:assets/image/x.png
data = ReadFromAssets("image/x.png",app);
二、其他目录
2~6路径作为根目录,在对应路径下创建或访问子文件或路径是可以的,用下列方法访问完整路径即可。遗憾的是,仅当app执行一次mkdir(filePath.c_str(), 0774)后,app才能正常读取创建的目录下的文件。当清楚app全部数据后,将会失去目录的读写权限,只有删除目录并让app重新创建才能使用。
#include <filesystem>
#include <sys/stat.h>
std::vector<char> ReadFileFromPath(const char* path) {
std::filesystem::path absolutePath(path);
auto filePath = absolutePath.parent_path();
struct stat sb{};
int32_t res = stat(filePath.c_str(), &sb);
if (0 == res && sb.st_mode & S_IFDIR)
{
//has dir
}
else if (ENOENT == errno)
{
//not has dir,create dir
res = mkdir(filePath.c_str(), 0774);
}
if(0!=res) return {};
std::ifstream file;
file.open(path, std::ifstream::in);
if(!file.is_open()){
return {};
}
file.seekg(0,std::ifstream ::end);
auto len = file.tellg();
std::vector<char> data;
if(len>0){
file.seekg(0,std::ifstream ::beg);
data.resize(len);
file.read(data.data(),static_cast<int>(len));
}
file.close();
return data;
}
example:
ReadFileFromPath("/storage/emulated/0/Android/data/com.example.org/files/data/123.obb");