12

私はAndroidでゲームエンジンを作成するためにエンジンで純粋なC++を使用しています。単一のJavaファイルはありません。基本的には外部メモリにのみ保存するゲームです。アセットデータをadb経由で外部SDカードに手動で移動すると、ゲームはすでに正常に動作し、安定しています。

adb push ..\..\Bin\Data /sdcard/Android/data/com.fantasyhaze.%SMALL_PACKAGE_NAME%/files/Data/

配信できないため、これは適切なソリューションではありません。したがって、次の構造でビルドプロセス中にapkファイルに移動されるAssetsフォルダーにassets-dataがあります。

Assets / Data / MoreFolders / Withsubfolders Assets / Data / EngineData.zip Assets / Data / ScriptData.zip

しかし、c++コードでそれらにアクセスするためにそれらのファイルがファイルシステムのどこにあるのかわかりません。

そこで、ファイルディレクトリへのパスを取得しようとしました。また、ネイティブアクティビティ状態のバグのため、通常のコードで情報を取得する必要があります。

// bug in 2.3 internalDataPath / externalDataPath = null using jni code instead
//FHZ_PRINTF("INTERNAL inter PATH = %s\n", state->activity->internalDataPath);  
//FHZ_PRINTF("EXTERNAL inter PATH = %s\n", state->activity->externalDataPath);

android.os.Environment.getFilesDir()およびandroid.os.Environment.getExternalStorageState()に相当するc++コード

            // getPath() - java
        JNIEnv *jni_env = Core::HAZEOS::GetJNIEnv();
        jclass cls_Env = jni_env->FindClass("android/app/NativeActivity");
        jmethodID mid_getExtStorage = jni_env->GetMethodID(cls_Env, "getFilesDir","()Ljava/io/File;");
        jobject obj_File = jni_env->CallObjectMethod( gstate->activity->clazz, mid_getExtStorage);
        jclass cls_File = jni_env->FindClass("java/io/File");
        jmethodID mid_getPath = jni_env->GetMethodID(cls_File, "getPath","()Ljava/lang/String;");
        jstring obj_Path = (jstring) jni_env->CallObjectMethod(obj_File, mid_getPath);
        const char* path = jni_env->GetStringUTFChars(obj_Path, NULL);
        FHZ_PRINTF("INTERNAL PATH = %s\n", path);
        jni_env->ReleaseStringUTFChars(obj_Path, path);

        // getCacheDir() - java
        mid_getExtStorage = jni_env->GetMethodID( cls_Env,"getCacheDir", "()Ljava/io/File;");
        obj_File = jni_env->CallObjectMethod(gstate->activity->clazz, mid_getExtStorage, NULL);
        cls_File = jni_env->FindClass("java/io/File");
        mid_getPath = jni_env->GetMethodID(cls_File, "getAbsolutePath", "()Ljava/lang/String;");
        obj_Path = (jstring) jni_env->CallObjectMethod(obj_File, mid_getPath);
        path = jni_env->GetStringUTFChars(obj_Path, NULL);
        FHZ_PRINTF("CACHE DIR = %s\n", path); 
        jni_env->ReleaseStringUTFChars(obj_Path, path);

        // getExternalFilesDir() - java
        mid_getExtStorage = jni_env->GetMethodID( cls_Env,"getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
        obj_File = jni_env->CallObjectMethod(gstate->activity->clazz, mid_getExtStorage, NULL);
        cls_File = jni_env->FindClass("java/io/File");
        mid_getPath = jni_env->GetMethodID(cls_File, "getPath", "()Ljava/lang/String;");
        obj_Path = (jstring) jni_env->CallObjectMethod(obj_File, mid_getPath);
        path = jni_env->GetStringUTFChars(obj_Path, NULL);
        FHZ_PRINTF("EXTERNAL PATH = %s\n", path);
        jni_env->ReleaseStringUTFChars(obj_Path, path);

        //getPackageCodePath() - java
        mid_getPath = jni_env->GetMethodID(cls_Env, "getPackageCodePath", "()Ljava/lang/String;"); 
        obj_File = jni_env->CallObjectMethod(gstate->activity->clazz, mid_getPath); 
        obj_Path = (jstring) jni_env->CallObjectMethod(obj_File, mid_getPath);
        path = jni_env->GetStringUTFChars(obj_Path, NULL);
        FHZ_PRINTF("Looked up package code path = %s\n", path);

これは非常にうまく機能し、結果として

内部パス=/data/data/com.fantasyhaze.rememory/files

CACHE DIR = /data/data/com.fantasyhaze.rememory/cache

外部パス=/mnt/sdcard/Android/data/com.fantasyhaze.rememory/files

ルックアップされたパッケージコードパス=/mnt/asec/com.fantasyhaze.rememory-2/pkg.apk

しかし、アセットフォルダからのファイルはありません...

ファイルを読み取るには、通常の作業ディレクトリとしてフォルダにアクセスする必要があります。これはで可能です

/mnt/sdcard/Android/data/com.fantasyhaze.rememory/files/Data

ただし、すべてのデータをアセットフォルダー(どこにある場合でも)からアセットマネージャーを介してこのフォルダーに移動すると、メモリの消費量が2倍になります。

資産>1GBは、資産> 2GBを意味しますが、これは意味がありません。それ以上に、assertフォルダーは、大きなpakファイルを使用する場合には不可能な小さなデータファイルに対してのみ、効果的に機能しないようです。たぶん、解凍システムを使用しているときにファイルにapkから直接アクセスしてから、リソースファイルをuzipすることができますが、とにかくapkパスを取得する必要があります。

だから私の質問:

  1. ファイルシステムのapkのAssetsフォルダーはどこにありますか?
  2. apkの場所または実行可能ファイルの場所を取得するためのコード(c ++)は何ですか?
  3. 通常のファイルを開く方法で直接アクセスできますか、それとも解凍した場合にのみアクセスできますか。開梱せずに使えるとしたらどうですか?
  4. SDカードがマウントされている場合に情報を取得するためのコード(c ++)は何ですか?

誰かが私を助けてくれることを願っています:)

編集:キャッシュディレクトリとパッケージディレクトリコード(およびその出力パス)を追加して、それを必要とする他のすべての人にソースを提供します。

4

2 に答える 2

2

「拡張ファイル」を確認することをお勧めします。APK拡張ファイルを参照してください。

私が理解している限り、これにより、リソースファイル(拡張ファイル)を「共有ストレージの場所」に自動的に配置するシステムが提供されます。

だから私はこれがあなたの重複データの問題を解決すると思います。

android-developersブログにも短い紹介記事があります。

于 2012-04-16T06:09:25.910 に答える
2

技術的には、ここにリンクする質問/回答で提供されているよりも詳細を求めているため、これを重複としてマークする代わりに回答を投稿しています。したがって、4 つの点のうち最初の点に答えるには、「C++ と NativeActivity クラスを使用して Android APK の名前を取得する」を参照してください。

SDカードがマウントされているかどうかの確認については、かなり単純なはずです。SD カード上のディレクトリまたはファイル (そこにあるはずであることがわかっている) を開こうとするだけで、失敗した場合は、SD カードが使用できないことがわかります。ファイルが C に存在するかどうかを確認する最良の方法は何ですか?を参照してください。(クロスプラットフォーム) .

于 2012-04-15T23:30:21.530 に答える