2017-01-16 5 views
5

Używam najnowszej wersji Androida Studio (2.2.3) i załadowałem przykładowy projekt HelloGL2.Jak dodać plik do projektu Android, a następnie załadować go za pomocą NDK

Chcę teraz dodać plik (dowolny typ pliku) do mojej aplikacji, a następnie być w stanie go otworzyć i odczytać w kodzie C++ za pomocą czegoś takiego jak c's fopen itp. (Jakikolwiek bezpośredni dostęp do pliku jest w porządku)

Jak to zrobić?

+0

Użyj ["Zasób"] (https://developer.android.com/ndk/reference/group___asset.html) lub podaj bezwzględną ścieżkę do pliku przez wywołanie JNI. – Onik

Odpowiedz

7

Dostępne są dwie opcje, zależy to od celu. Jeśli plik jest podstawowym plikiem konfiguracji tekstowej, możesz użyć obu przypadków, ale jeśli Twój plik jest obiektem 3D, takim jak (.obj, .max, .dae), powinieneś użyć klasy AssetManager.

Pierwsza opcja: (przechowuj pliki w res raw (możesz użyć fopen())).

  • Utwórz folder o nazwie surowy wewnątrz katalogu res (li-> RAW).
  • Zapisz swoje pliki w prywatnym katalogu apk.

W Javie:

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(); 
     }     
    } 

Następnie zadzwonić do funkcji:

 writeFileToPrivateStorage(R.raw.your_file,"your_output_file.txt"); 
  • Pobierz prywatny ścieżka
 
    path=mContext.getApplicationContext().getFilesDir().toString(); 
  • Zdefiniuj función JNI w Javie:
 
    public static native void setconfiguration(String yourpath); 
  • wdrożyć go w 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"); 
     } 

Druga opcja (użyj assetManager, zwykle dla OpenGL zasobów).

Parametr, w tym przypadku nie jest ścieżką do katalogu, jest menedżerem aktywów.

  • Przechowuj pliki w katalogu zasobów.
  • Zdefiniuj natywną funkcję w C/C++
 
    public static native void yourfunction(AssetManager assetManager); 
  • połączenia w java do tej funkcji:
 
    loadYourFile(m_context.getAssets()); 
  • Stwórz swoją funkcję JNI w C/C++
 
    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); 
     } 

Uwaga: Nie zapomnij dodać uprawnień do pliku AndroidManifest.xml.

Uwaga II: Nie zapomnij dodać:

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

Mam nadzieję, że ta odpowiedź pomaga.

+0

Wielkie dzięki! tak trudno było znaleźć wyraźny przykład na ten temat. Zastanawiasz się, czy to złe zachowanie, aby zachować wskaźnik mgr i używać go później? więc wystarczy jednorazowo przekazać menedżer zasobów do natywnego kodu, a następnie za pomocą tego wskaźnika załadować zasoby w czasie życia aplikacji w natywnym kodzie? – matt

+1

masz rację: @matt, nie jest złym pomysłem, aby zachować wskaźnik mgr, zazwyczaj używam funkcji setterFunction, jak setAssetManager(), aby zachować moje klasy ładujące biblioteki OpenGL. – uelordi

+1

Jeszcze jedno, jeśli twoim celem jest załadowanie obiektów 3D, użyj biblioteki 3D http://www.assimp.org/. Twoje zdrowie. – uelordi

Powiązane problemy