直接在c ++中访问Android APK资产数据,无需Asset Manager和复制

11 c++ android native apk native-activity

我在我的引擎中使用纯C++在android中创建游戏引擎.没有单个java文件.基本上它是一个只应存储到外部存储器的游戏.当我通过adb手动将我的资产数据移动到我的外部SD卡时,游戏运行良好且稳定.

adb push ..\..\Bin\Data /sdcard/Android/data/com.fantasyhaze.%SMALL_PACKAGE_NAME%/files/Data/
Run Code Online (Sandbox Code Playgroud)

这不是一个好的解决方案,因为它无法交付.因此,我在Assets文件夹中的资产数据在构建过程中被移动到apk文件中,具有以下结构:

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);
Run Code Online (Sandbox Code Playgroud)

相当于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);
Run Code Online (Sandbox Code Playgroud)

哪个效果很好而且效果很好

内部路径= /data/data/com.fantasyhaze.rememory/files

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

EXTERNAL PATH = /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

但是,通过资产管理器将资产文件夹(无论它在何处)的所有数据移动到此文件夹,会导致内存消耗增加一倍.

资产> 1GB意味着资产> 2GB,这是没有意义的.不仅如此,assert文件夹似乎不能反复使用,只适用于使用较大的pak文件时不可能的小数据文件.也许这些文件可以在使用解压缩系统时直接从apk访问,然后解压缩我的资源文件,但因此无论如何我都必须获取apk路径.

所以我的问题:

  1. 文件系统上apk中的Assets文件夹在哪里?
  2. 检索apk位置或可执行文件位置的代码(c ++)是什么?
  3. 我可以使用普通的文件打开方法直接访问它,也可以只在解压缩时才能访问它.如果我可以在不拆包的情况下使用它,怎么样?
  4. 如果安装了SD卡,检索信息的代码(c ++)是什么?

我希望有一个人可以帮助我 :)

编辑:添加了缓存目录和包目录代码(以及它的输出路径),以便为需要它的其他人提供源代码.

小智 2

我发布一个答案,而不是将其标记为重复,因为从技术上讲,您要求提供的详细信息比我将在此处链接的问题/答案中提供的更多详细信息。因此,要回答您的 4 点中的第一点,请参阅使用 C++ 和 NativeActivity 类获取 Android APK 的名称

至于检查SD卡是否安装,应该是比较简单的。只需尝试打开 SD 卡上的目录或文件(您知道应该在那里),如果失败,您就知道 SD 卡不可用。请参阅检查 C 中文件是否存在的最佳方法是什么?(跨平台)