2013-08-06 8 views
5

2010年以前のソリューションしか見つかりませんでした。だから私はこれにもっと最新の姿勢があるかどうかを見たいと思っていました。AndroidのNativeActivityのfopen/fread APKアセット

Javaを使用せず、純粋にC++を使用して、APKに保存されているファイル(1MB以下)にアクセスしたいと思います。 AssetManagerを使用すると、ほかのすべてのオペレーティングシステム(iOSを含む)のすべてのファイルと同じようにファイルにアクセスできなくなります。

もしそうでなければ、私は何とかfopen/freadをAssetManager APIにマップすることができるC++のメソッドがありますか? AAssetManagerにC++でのfopen

+1

アセットはファイルではないため、答えは「ノー」と考えられます。アセットは、APKであるZIPアーカイブのエントリです。 – CommonsWare

+0

'良い点です... –

+0

技術的には、APKは派手なzipファイルなので、APK内の任意のファイルにアクセスすることは、C++のzipファイルのように完全に可能です。しかし、いくつかの* javaが必要ですが、apkのインストール場所を取得するだけです。私は事実を知っていることは問題ではありませんが、私はAPKに執筆しようとしたことはありません。 – Erik

答えて

6

短い答え

号の私の知る限りマッピング関数fread /はできません。もしそうであれば、おそらく資産フォルダのファイルに制限されるでしょう。しかし、回避策はありますが、それは簡単ではありません。

ロング回答

それは、は、C++でのzlibとlibzipを使用して任意の場所にAPK内のすべてのファイルにアクセスすることも可能です。 要件:いくつかのJava、zlib、libzip(使いやすさのために、私はそれを解決しました)ここでlibzipを入手することができます:http://www.nih.at/libzip/

libzipは、それがアンドロイドで動作するようにするにはいくつかの変更が必要かもしれませんが、深刻なことはありません。

ステップ1:JavaでAPKの場所を取得し、JNI/C++ CにPathToAPKを渡す

String PathToAPK; 
ApplicationInfo appInfo = null; 
PackageManager packMgmr = parent.getPackageManager(); 
try { 
    appInfo = packMgmr.getApplicationInfo("com.your.application", 0); 
} catch (NameNotFoundException e) { 
    e.printStackTrace(); 
    throw new RuntimeException("Unable to locate APK..."); 
} 

PathToAPK = appInfo.sourceDir; 

++/JNI

JNIEXPORT jlong JNICALL Java_com_your_app(JNIEnv *env, jobject obj, jstring PathToAPK) 
{ 
    // convert strings 
    const char *apk_location = env->GetStringUTFChars(PathToAPK, 0); 

    // Do some assigning, data init, whatever... 
    // insert code here 

    //release strings 
    env->ReleaseStringUTFChars(PathToAPK, apk_location); 

    return 0; 
} 

あなたが今STDを持っていると仮定すると::文字列に渡しますあなたのAPKの場所とあなたはlibzipでzlibを使って次のようなことができます:

if(apk_open == false) 
{ 
    apk_file = zip_open(apk_location.c_str(), 0, NULL); 

    if(apk_file == NULL) 
    { 
     LOGE("Error opening APK!"); 
     result = ASSET_APK_NOT_FOUND_ERROR; 
    }else 
    { 
     apk_open = true; 
     result = ASSET_NO_ERROR; 
    } 
} 

そして、APKファイルから読み込むため:

if(apk_file != NULL){ 
    // file you wish to read; **any** file from the APK, you're not limited to regular assets 
    const char *file_name = "path/to/file.png"; 

    int file_index; 
    zip_file *file; 
    struct zip_stat file_stat; 

    file_index = zip_name_locate(apk_file, file_name, 0); 

    if(file_index == -1) 
    { 
     zip_close(apk_file); 
     apk_open = false; 

     return; 
    } 

    file = zip_fopen_index(apk_file, file_index, 0); 
    if(file == NULL) 
    { 
     zip_close(apk_file); 
     apk_open = false; 

     return; 
    } 

    // get the file stats 
    zip_stat_init(&file_stat); 
    zip_stat(apk_file, file_name, 0, &file_stat); 
    char *buffer = new char[file_stat.size]; 

    // read the file 
    int result = zip_fread(file, buffer, file_stat.size); 
    if(result == -1) 
    { 
     delete[] buffer; 
     zip_fclose(file); 

     zip_close(apk_file); 
     apk_open = false; 

     return; 
    } 

    // do something with the file 
    // code goes here 

    // delete the buffer, close the file and apk 
    delete[] buffer; 
    zip_fclose(file); 

    zip_close(apk_file); 
    apk_open = false; 

正確に/ fread関数はfopenが、それは仕事を取得されていません。 zipレイヤーを抽象化するために、これをあなた自身のファイル読み取り関数にラップするのはかなり簡単です。

+0

libzは最近、Androidのツールチェーンによって提供されています - libzip上で使用する際に危険がありますか?彼らは違う/同じですか? –

+0

全くありません。私はアンドロイド提供のlibzも使用しています。 libzipは一番上のlibzに置かれたライブラリで、読み書きを少し楽にします。 – Erik

+1

クイックフィックスでは、バッファでdelete []を削除しないでください。 –

8

私は実際に問題とかなりのエレガントな答えとblogged about it hereを見つけました。

概要は次のとおりです。

  • AAssetManagerのAPIは、NDKバインディングを持っています。これにより、APKからアセットを読み込むことができます。
  • 何かを読み書きする方法を知っている関数のセットを組み合わせて、それらをファイルポインタ(FILE *)として偽装することは可能です。
  • 資産名を取る関数を作成し、AssetManagerを使用してその関数を開き、その結果をFILE *として偽装すると、fopenと非常によく似たものがあります。
  • fopenという名前のマクロを定義した場合、その関数のすべての使用を代わりに使用することができます。

私のブログには完全な書込みがあり、純粋なCで実装する必要があるすべてのコードがあります。これを使ってAndroid用のluaとliboggをビルドします。

+1

ファイルサイズ: 'size_t file_size(FILE * fp){ android_seek(fp、0L、SEEK_END); size_t sz = ftell(fp); android_seek(fp、0L、SEEK_SET); return sz; } ' –

関連する問題