【问题标题】:How do I add a file to an Android project and then load it using the NDK如何将文件添加到 Android 项目,然后使用 NDK 加载它
【发布时间】:2017-01-16 10:54:49
【问题描述】:

我使用的是最新版本的 Android Studio (2.2.3),并且我已经加载了 HelloGL2 示例项目。

我现在想在我的应用程序中添加一个文件(任何类型的文件),然后能够打开它并使用 c 的 fopen 等在 c++ 代码中读取它(任何直接文件访问 api 都可以)

我该怎么做?

【问题讨论】:

  • 使用 Asset 或通过 JNI 调用将绝对路径传递给文件。

标签: android c++ file-io android-ndk


【解决方案1】:

有两种选择,这取决于您的目标。 如果您的文件是基本文本配置文件,您可以同时使用这两种情况,但如果您的文件是 3D 对象,例如 (.obj, .max, .dae),您应该使用 AssetManager 类。

第一个选项:(将文件存储在 res raw 中(您可以使用 fopen()))。

  • 在 res 目录 (res->raw) 中创建一个名为 raw 的文件夹。
  • 将文件写入 apk 私有目录。

在 Java 中:

    public void writeFileToPrivateStorage(int fromFile, String toFile) 
    {

       InputStream is =   mContext.getResources().openRawResource(fromFile);
       int bytes_read;
       byte[] buffer = new byte[4096];  
         try 
         {
            FileOutputStream fos = mContext.openFileOutput(toFile, Context.MODE_PRIVATE);

            while ((bytes_read = is.read(buffer)) != -1)            
                fos.write(buffer, 0, bytes_read); // write

            fos.close();
            is.close();

        } 
        catch (FileNotFoundException e) 
        {            
            e.printStackTrace();
        } 
         catch (IOException e) 
         {            
            e.printStackTrace();
        }                 
    }  

然后,调用你的函数:

        writeFileToPrivateStorage(R.raw.your_file,"your_output_file.txt");
  • 获取您的私有路径
path=mContext.getApplicationContext().getFilesDir().toString();
  • 在 Java 中定义您的 JNI 函数:
public static native void setconfiguration(String yourpath);
  • 用 C/C++ 实现它:
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_setconfiguration(JNIEnv * env, jobject obj, jstring 路径) { //将你的字符串转换成std::string。 const char *nativeString = env->GetStringUTFChars(config_path, 0); //在这里做你的fopen。 fopen(nativeString,"r"); }

第二个选项(使用assetManager,通常用于opengl资源)。

参数,在这种情况下,不是目录的路径是资产管理器。

  • 将文件存储在资产目录中。
  • 在 C/C++ 中定义您的本机函数
public static native void yourfunction(AssetManagerassetManager);
  • 在java中调用这个函数:
loadYourFile(m_context.getAssets());
  • 在 C/C++ 中创建您的 jni 函数
JNIEXPORT void Java_com_android_gl2jni_GL2JNILib_(JNIEnv * env, jobject obj,jobject java_asset_manager) { AAssetManager* mgr = AAssetManager_fromJava(env,java_asset_manager); AAsset* 资产 = AAssetManager_open(mgr, (const char *) js, AASSET_MODE_UNKNOWN); 如果(NULL == 资产){ __android_log_print(ANDROID_LOG_ERROR, NF_LOG_TAG, "_ASSET_NOT_FOUND_"); 返回 JNI_FALSE; } 长尺寸 = AAsset_getLength(asset); char* 缓冲区 = (char*) malloc (sizeof(char)*size); AAsset_read(资产,缓冲区,大小); __android_log_print(ANDROID_LOG_ERROR, NF_LOG_TAG, 缓冲区); AAsset_close(资产); }

注意:不要忘记在您的 AndroidManifest.xml 中添加权限。

注意二:别忘了补充:

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

希望这个回答对你有帮助。

【讨论】:

  • 非常感谢!很难找到一个明确的例子。只是想知道,保留 mgr 指针并在以后使用它是一种不好的形式吗?所以只需将资产管理器传递给本机代码一次,然后使用该指针在本机代码中的应用程序生命周期内加载资产?
  • 你是对的@matt,保留mgr指针也不错,我通常使用setAssetManager()之类的setterFunction来保留我的opengl资源加载器类。
  • 还有一点,如果您的最终目标是加载 3D 对象,请使用 assimp 3D 库assimp.org。干杯。
  • 那个库看起来棒极了!
猜你喜欢
  • 1970-01-01
  • 2017-05-29
  • 2011-04-09
  • 2019-05-03
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多