2017-01-16 48 views
5

我正在使用最新版本的Android Studio(2.2.3),并加载了HelloGL2示例项目。如何将文件添加到Android项目,然后使用NDK加载它

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

我该怎么做?

+0

使用['Asset'](https://developer.android.com/ndk/reference/group___asset.html)或通过JNI调用将绝对路径传递给文件。 – Onik

回答

7

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

第一个选项:(将原始文件保存为原始文件(可以使用fopen()))。

  • 创建名为原料内部res目录(水库>生的)文件夹。
  • 将你的文件写入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(); 
  • 定义你的JNI funcion在Java中:
 
    public static native void setconfiguration(String yourpath); 
  • 在C/C++实现:
 
    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_setconfiguration(JNIEnv * env, jobject obj, jstring path) 
     { 
      //convert your string into std::string. 
      const char *nativeString = env->GetStringUTFChars(config_path, 0); 
      //make here your fopen. 
      fopen(nativeString,"r"); 
     } 

第二个选项(使用assetManager,通常是OpenGL的资源)。

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

  • 将您的文件存储在资产目录中。
  • /C++
 
    public static native void yourfunction(AssetManager assetManager); 
  • 在Java调用定义你的本地函数在C这样的功能:
 
    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* asset = AAssetManager_open(mgr, (const char *) js, AASSET_MODE_UNKNOWN); 
      if (NULL == asset) { 
       __android_log_print(ANDROID_LOG_ERROR, NF_LOG_TAG, "_ASSET_NOT_FOUND_"); 
       return JNI_FALSE; 
      } 
      long size = AAsset_getLength(asset); 
      char* buffer = (char*) malloc (sizeof(char)*size); 
      AAsset_read (asset,buffer,size); 
      __android_log_print(ANDROID_LOG_ERROR, NF_LOG_TAG, buffer); 
      AAsset_close(asset); 
     } 

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

注二:不要忘了补充:

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

我希望这个答案可以帮助你。

+0

非常感谢!很难找到一个明确的例子。 只是想知道,保留mgr指针并在以后使用它是不好的形式吗?所以只需将资产管理器传递给本机代码一次,然后使用该指针在本机代码的应用程序生命周期中加载资产? – matt

+1

你是对的@matt,保留mgr指针是不错的主意,我通常使用setterFunction像setAssetManager()来保存在我的opengl资源加载器类中。 – uelordi

+1

还有一件事,如果您的最终目标是加载3D对象,请使用assimp 3D库http://www.assimp.org/。干杯。 – uelordi

相关问题