2011-09-29 20 views
18

Obecnie pracuję nad opartą na C, opartą na NDK aplikacją na Androida. Ta aplikacja musi utworzyć pliki tymczasowe. W zwykłym systemie Linux użyłbym tmpfile, aby zapewnić, że pliki te są poprawnie tworzone w katalogu tymczasowym i czyszczone po zakończeniu procesu.Tworzenie plików tymczasowych w systemie Android przy użyciu NDK

Jednak moje badania na różnych urządzeniach z Androidem wydają się wskazywać, że

  • tmpfile zawsze kończy się niepowodzeniem;
  • nie ma katalogu /tmp;
  • katalog /data/local/tmp nie występuje we wszystkich wariantach Androida;
  • nie ma zestawu zmiennych środowiskowych;
  • mkstemp nie działa lepiej niż tmpfile.

Teraz jestem pewien, że mogę siekać coś razem, ale widząc, że SDK oferuje context.getCacheDir i File.createTempFile dla aplikacji Java, mam nadzieję, że istnieje odpowiednik w C-poziom.

Czy ktoś wie o dobrej niezawodnej i wielozadaniowej metodzie tworzenia tymczasowego pliku?

Odpowiedz

9

Najlepszym sposobem, jaki znaleźliśmy, jest zadzwonienie pod numer Context.getCacheDir po uruchomieniu, uzyskanie jego ścieżki za pomocą getAbsolutePath, a następnie wywołanie funkcji JNI w celu zapisania tej ścieżki w globalnej. Każda funkcja, która chce utworzyć plik tymczasowy, po prostu dołącza do tej ścieżki odpowiednią tymczasową nazwę pliku.

Jeśli naprawdę chcesz, aby sprowadzić go z JNI Inną alternatywą byłoby przekazać w Context do funkcji JNI i używać kilka GetMethodID/CallObjectMethod rzeczy oddzwonić do Java getCacheDir, ale pierwsze podejście jest dużo prostsze.

Niestety, obecnie nie ma bardziej eleganckiego rozwiązania.

+2

Możliwe jest użycie 'libcore' do wywołania' setenv() ', patrz http://stackoverflow.com/a/22315463/192373. Może to być bardziej elegancki sposób na pokazanie nazwy katalogu pamięci podręcznej na natywny. –

0

mkstemp jest dostępny w NDK pod stdlib.h

+0

Czy to pomaga? Myślę, że mkstemp pobiera "szablon" zawierający pełną ścieżkę do katalogu tymczasowego. –

2

Poniżej procedura GetMethodID/CallObjectMethod że Ertebolle odnosi. Jest to konieczne, jeśli pracujesz z czysto natywną aplikacją (taką jak zbudowana przez Visual Studio 2015) i nie możesz używać kodu Java.

std::string android_temp_folder(struct android_app *app) { 
    JNIEnv* env; 
    app->activity->vm->AttachCurrentThread(&env, NULL); 

    jclass activityClass = env->FindClass("android/app/NativeActivity"); 
    jmethodID getCacheDir = env->GetMethodID(activityClass, "getCacheDir", "()Ljava/io/File;"); 
    jobject cache_dir = env->CallObjectMethod(app->activity->clazz, getCacheDir); 

    jclass fileClass = env->FindClass("java/io/File"); 
    jmethodID getPath = env->GetMethodID(fileClass, "getPath", "()Ljava/lang/String;"); 
    jstring path_string = (jstring)env->CallObjectMethod(cache_dir, getPath); 

    const char *path_chars = env->GetStringUTFChars(path_string, NULL); 
    std::string temp_folder(path_chars); 

    env->ReleaseStringUTFChars(path_string, path_chars); 
    app->activity->vm->DetachCurrentThread(); 
    return temp_folder; 
} 
Powiązane problemy