2012-07-02 21 views
22

ネイティブコードからファイルを保存します。 私は次の構造を抱えている:アンドロイド - 書き込み/私はNDKの<code>NativeActivity</code>施設を利用したAndroidアプリを構築しようとしているだけ

  • /system/vendor/<company>にインストールネイティブ共有ライブラリの束。 適切な権限と、すべて
上記のライブラリ に順番に依存 NativeActivityを使用したアプリケーションのカップルであったライブラリを持つ何ら問題はありませんので、私は、カスタム構築されたAndroidのイメージで を働いています

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

これらのファイルを作成して保存するにはどのような方法がありますか。 「Androidに準拠」の保存領域はどこですか?

私はandroid-ndk Googleグループで、the internal application private storageまたはthe external SD cardのいずれかを指しているSOのスレッドをいくつか読んできましたが、Androidの拡張された経験はないため、適切なアプローチ。特定のAndroid APIが含まれているアプローチの場合、C++の小さなコード例が非常に役に立ちます。私は、JavaとJNI(e.g. in this SO question)を含むいくつかの例を見てきましたが、私は今それを離れていきたいと思います。 はまた、ネイティブの活動の internalDataPath/externalDataPathペア(a bug that makes them be always NULL)C++から使用に問題があるように思われます。

答えて

23

比較的小さなファイル(アプリケーション設定ファイル、パラメータファイル、ログファイルなど)の場合 は、内部アプリケーションのプライベートストレージ(/data/data/<package>/files)を使用することをお勧めします。 頻繁なアクセスや更新を必要としない大容量のファイルには、外部記憶装置が存在する場合(SDカードであるかどうかにかかわらず)、外部記憶装置を使用する必要があります。 APIかもしれない(利用可能な場合またはC++ストリーム同等物)

<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の場合

:外部データストレージ用

は、ネイティブアプリケーションは、アプリケーションのAndroidManifest.xml中に「要求」適切な権限を持っています中古。次の例は、Android NDK AssetManagerを使用して設定ファイルを取得して読み取る方法を示しています。このファイルは、ネイティブアプリケーションのプロジェクトフォルダ内のassetsディレクトリに配置する必要があります。これにより、NDKビルドが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); 
     } 
    } 
} 
関連する問題