28

NativeActivityNDKの機能を利用したAndroidアプリを作ろうとしています。私は次の構造を持っています:

  • にインストールされているネイティブ共有ライブラリの束/system/vendor/<company>。私はカスタムビルドのAndroidイメージを使用しているので、適切な権限とすべてを備えたライブラリが問題なく存在します
  • NativeActivity上記のライブラリに順番に依存するを使用するいくつかのアプリケーション

/ system / vendorにインストールされているライブラリと私のアプリケーションは、いくつかの構成ファイルを使用しています。標準のCAPIを使用してそれらを読むのに問題はありません fopen/fclose。しかし、これらのライブラリと私のアプリケーションは、構成、実行時パラメーター、キャリブレーションデータ、ログファイルなど、操作の結果としていくつかのファイルも保存する必要があります。ファイルの保存には、私がしているようにわずかな問題があります。書き込みは許可されていません/system/vendor/...(「/ system / ...」の下のファイルシステムは読み取り専用でマウントされており、ハッキングしたくないため)。

では、これらのファイルを作成して保存するための最良の方法は何でしょうか。また、「Androidに準拠した」ストレージ領域として最適な場所はどこでしょうか。

私はandroid-ndkGoogleグループのいくつかのスレッドを読んでいて、ここでは内部アプリケーションのプライベートストレージまたは外部SDカードのいずれかに言及していますが、Androidの経験が豊富ではないため、何がわかりません適切なアプローチになります。アプローチに特定のAndroidAPIが含まれる場合は、C++の小さなコード例が非常に役立ちます。JavaとJNIに関連するいくつかの例を見てきましたが(たとえば、このSOの質問で)、今はそれを避けたいと思います。internalDataPath/externalDataPathまた、C ++からネイティブアクティビティのペアを使用することに問題があるようです (それらを常にNULLにするバグ)。

4

1 に答える 1

29

比較的小さいファイル(アプリケーション構成ファイル、パラメーターファイル、ログファイルなど)の場合は、内部アプリケーションのプライベートストレージを使用するのが最適です/data/data/<package>/files。外部ストレージが存在する場合(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 ++ストリームに相当するもの)APIを使用できます。次の例は、AndroidNDKAssetManagerを使用して構成ファイルを取得および読み取る方法を示しています。assetsNDKビルドがAPK内にパックできるように、ファイルはネイティブアプリケーションのプロジェクトフォルダー内のディレクトリに配置する必要があります。質問で言及したinternalDataPath/externalDataPathバグは、NDKr8バージョンで修正されました。

...
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);
        }
    }
}
于 2012-07-18T08:49:30.687 に答える