Создание временных файлов в Android с помощью NDK
В настоящее время я работаю над приложением на базе Android на базе NDK. Это приложение должно создавать временные файлы. В обычной системе Linux я использовал бы tmpfile
, чтобы эти файлы были правильно созданы во временном каталоге и очищены на завершении процесса.
Однако мои исследования на разных устройствах Android, похоже, указывают на то, что
-
tmpfile
всегда терпит неудачу;
- нет каталога
/tmp
;
- каталог
/data/local/tmp
отсутствует во всех вариантах Android;
- нет набора переменных окружения
TEMP
;
-
mkstemp
не работает лучше, чем tmpfile
.
Теперь я уверен, что могу что-то взломать, но, увидев, что SDK предлагает context.getCacheDir
и File.createTempFile
для Java-приложений, я надеюсь, что на уровне C есть эквивалент.
Кто-нибудь знает о хорошем надежном и перекрестном методе Android для создания временного файла?
Ответы
Ответ 1
Лучший способ, который мы нашли, - вызвать Context.getCacheDir
при запуске, получить его путь с помощью getAbsolutePath
, а затем вызвать функцию JNI для хранения этого пути в глобальном. Любая функция, которая хочет создать временный файл, просто добавляет подходящее временное имя файла к этому пути.
Если вы действительно хотите извлечь его из JNI, другой альтернативой было бы передать в Context
функцию JNI и использовать связку GetMethodID
/CallObjectMethod
для пересылки на Java на getCacheDir
, но прежний подход намного проще.
К сожалению, на данный момент не существует более элегантного решения.
Ответ 2
Ниже приведена процедура GetMethodID/CallObjectMethod, к которой относится Ertebolle. Это необходимо, если вы работаете с чистым родным приложением (например, созданным Visual Studio 2015) и не можете использовать 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;
}
Ответ 3
Насколько я знаю, в android нет глобального /tmp, вы должны использовать кеш-каталог. Используйте getCacheDir(), чтобы получить директорию "tmp".
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal и http://developer.android.com/reference/android/content/Context.html#getCacheDir%28%29
Ответ 4
mkstemp доступен в NDK под stdlib.h
Ответ 5
- Получите путь к каталогу кэша при запуске приложения с помощью ContentProvider.
- Реализуйте функцию tmpfile с той же сигнатурой, что и в POSIX tmpfile.
- Вызовите mkstemp из функции tmpfile, используя ранее полученный каталог кеша
Упаковано как .aar, так что его можно использовать через gradle.
https://github.com/ViliusSutkus/tmpfile