Android – 仅从本地代码写入/保存文件

我正在尝试构build一个使用NDK的NativeActivity工具的Android应用程序。 我有以下结构:

  • 安装在/system/vendor/<company>的一些本地共享库; 我正在使用一个自定义的Android图像,所以有没有适当的权限和一切的图书馆没有问题
  • 一些使用NativeActivity的应用依次取决于上面提到的库

安装在/ system / vendor和我的应用程序中的库使用了一些configuration文件。 使用标准的C API fopen/fclose读取它们没有任何问题。 但是,这些库和我的应用程序也需要存储一些文件作为其操作的结果,如configuration,一些运行时参数,校准数据,日志文件等。随着文件的存储有一个小问题,因为我不允许写入/system/vendor/... (因为“/ system / …”下的文件系统是只读的,所以我不想破解它)。

那么创build和存储这些文件的最佳方式是什么?哪里才是最符合Android标准的存储区?

我一直在阅读android-ndk Google小组中的几个主题,在这里提到内部应用程序私有存储或外部SD卡 ,但由于我没有Android的扩展经验,我不确定是什么将是正确的做法。 如果方法涉及到一些特定的Android API,那么C ++中的一个小代码将非常有用。 我已经看到了几个涉及Java和JNI的例子( 例如,在这个SO问题中 ),但是现在我想远离它。 从C ++使用本地活动的internalDataPath/externalDataPath对( 使它们始终为NULL的错误)似乎也有问题。

Solutions Collecting From Web of "Android – 仅从本地代码写入/保存文件"

对于相对较小的文件(应用程序configuration文件,参数文件,日志文件等),最好使用内部应用程序专用存储,即/data/data/<package>/files 。 如果存在外部存储(不pipe是否为SD卡),则应该用于不需要频繁访问或更新的大文件。

对于外部数据存储,本机应用程序必须在应用程序的AndroidManifest.xml “请求”正确的权限:

 <manifest> ... <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> </uses-permission> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"> </uses-permission> </manifest> 

对于内部应用程序私有存储fopen/fclose (或C ++stream等效项(如果可用))可以使用API​​。 以下示例说明如何使用Android NDK AssetManager来检索和读取configuration文件。 该文件必须放置在本机应用程序项目文件夹内的assets目录中,以便NDK构build可以将它们打包到APK中。 我在这个问题中提到的internalDataPath/externalDataPath错误是针对NDK r8版本修复的。

 ... void android_main(struct android_app* state) { // Make sure glue isn't stripped app_dummy(); ANativeActivity* nativeActivity = state->activity; const char* internalPath = nativeActivity->internalDataPath; std::string dataPath(internalPath); // internalDataPath points directly to the files/ directory std::string configFile = dataPath + "/app_config.xml"; // sometimes if this is the first time we run the app // then we need to create the internal storage "files" directory struct stat sb; int32_t res = stat(dataPath.c_str(), &sb); if (0 == res && sb.st_mode & S_IFDIR) { LOGD("'files/' dir already in app's internal data storage."); } else if (ENOENT == errno) { res = mkdir(dataPath.c_str(), 0770); } if (0 == res) { // test to see if the config file is already present res = stat(configFile.c_str(), &sb); if (0 == res && sb.st_mode & S_IFREG) { LOGI("Application config file already present"); } else { LOGI("Application config file does not exist. Creating it ..."); // read our application config file from the assets inside the apk // save the config file contents in the application's internal storage LOGD("Reading config file using the asset manager.\n"); AAssetManager* assetManager = nativeActivity->assetManager; AAsset* configFileAsset = AAssetManager_open(assetManager, "app_config.xml", AASSET_MODE_BUFFER); const void* configData = AAsset_getBuffer(configFileAsset); const off_t configLen = AAsset_getLength(configFileAsset); FILE* appConfigFile = std::fopen(configFile.c_str(), "w+"); if (NULL == appConfigFile) { LOGE("Could not create app configuration file.\n"); } else { LOGI("App config file created successfully. Writing config data ...\n"); res = std::fwrite(configData, sizeof(char), configLen, appConfigFile); if (configLen != res) { LOGE("Error generating app configuration file.\n"); } } std::fclose(appConfigFile); AAsset_close(configFileAsset); } } }