Android - 仅从本机代码写入/保存文件 [英] Android - writing/saving files from native code only

查看:8
本文介绍了Android - 仅从本机代码写入/保存文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个使用 NDK 的 NativeActivity 工具的 Android 应用.我有以下结构:

I'm trying to build an Android app which makes use of the NativeActivity facility of the NDK. I'm having the following structure:

  • 安装在/system/vendor/<company>中的一堆原生共享库;我在工作使用自定义构建的 Android 图像,因此库没有问题适当的权限和一切
  • 几个使用 NativeActivity 的应用程序,它们依次依赖于库上面提到的
  • a bunch of native shared libraries installed in /system/vendor/<company>; I'm working with a custom built Android image so there's no problem having the libraries there with proper permissions and everything
  • a couple of applications using the NativeActivity that depend in turn on the libraries mentioned above

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

The libraries installed in the /system/vendor and my applications use a couple of configuration files. There's no problem reading them using the standard C API fopen/fclose. But those libraries and my application also need to store some files as the result of their operation, like configuration, some run-time parameters, calibration data, log files etc. With the storing of the files there is a slight issue as I'm not allowed to write into /system/vendor/... (as the file system under "/system/..." is mounted read-only and I do not want to hack on that).

那么创建和存储这些文件的最佳方式是什么?最好的符合安卓"的存储区?

So what would be the best way to create and store those files and where would be the best "conforming with Android" storage area ?

我一直在阅读 android-ndk Google 组中的几个线程,并且在这里提到 内部应用程序私有存储外部 SD 卡,但由于我没有丰富的 Android 经验,我不确定什么是正确的方法.如果该方法涉及某些特定的 Android API,则 C++ 中的小代码示例将非常有帮助;我见过几个涉及 Java 和 JNI 的示例(例如在这个 SO 问题中)但是我现在想远离那个.从 C++ 使用本机活动似乎也存在问题internalDataPath/externalDataPath 对(一个使它们始终为 NULL 的错误).

I've been reading a couple of threads in the android-ndk Google group and here on SO that mention either the internal application private storage or the external SD card, but as I do not have extended experience with Android I'm not sure what would be the proper approach. If the approach involves some specific Android API a small code example in C++ would be very helpful; I've seen a couple of examples involving Java and JNI (e.g. in this SO question) but I would like to stay away from that right now. Also there seems to be a problem with using from C++ the native activity's internalDataPath/externalDataPath pair (a bug that makes them be always NULL).

推荐答案

对于比较小的文件(应用配置文件、参数文件、日志文件等)最好使用内部应用私有存储,即/data/data//files.如果外部存储存在(无论是否为 SD 卡),则应将其用于不需要频繁访问或更新的大文件.

For relatively small files(application config files, parameter files, log files etc.) is best to use the internal application private storage, that is /data/data/<package>/files. The external storage if it exists at all (being it SD card or not) should be used for large files that do not need frequent access or updates.

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

For the external data storage the native application has to "request" the correct permissions in the application's 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++ 流等效项,如果可用)可以使用 API.以下示例说明了使用 Android NDK AssetManager 检索和读取配置文件.该文件必须放在本机应用程序项目文件夹内的 assets 目录中,以便 NDK 构建可以将它们打包到 APK 中.我在问题中提到的 internalDataPath/externalDataPath 错误已针对 NDK r8 版本进行了修复.

For the internal application private storage fopen/fclose(or C++ stream equivalents if available) API could be used. Following example illustrates using the Android NDK AssetManager to retrieve and read a configuration file. The file must be placed into the assets directory inside the native application’s project folder so that the NDK build could pack them inside the APK. The internalDataPath/externalDataPath bug I was mentioning in the question was fixed for the NDK r8 version.

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

            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.
");
            }
            else
            {
                LOGI("App config file created successfully. Writing config data ...
");
                res = std::fwrite(configData, sizeof(char), configLen, appConfigFile);
                if (configLen != res)
                {
                    LOGE("Error generating app configuration file.
");
                }
            }
            std::fclose(appConfigFile);
            AAsset_close(configFileAsset);
        }
    }
}

这篇关于Android - 仅从本机代码写入/保存文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆