Подтвердить что ты не робот

Создание временных файлов в Android с помощью NDK

В настоящее время я работаю над приложением на базе Android на базе NDK. Это приложение должно создавать временные файлы. В обычной системе Linux я использовал бы tmpfile, чтобы эти файлы были правильно созданы во временном каталоге и очищены на завершении процесса.

Однако мои исследования на разных устройствах Android, похоже, указывают на то, что

  • tmpfile всегда терпит неудачу;
  • нет каталога /tmp;
  • каталог /data/local/tmp отсутствует во всех вариантах Android;
  • нет набора переменных окружения TEMP;
  • mkstemp не работает лучше, чем tmpfile.

Теперь я уверен, что могу что-то взломать, но, увидев, что SDK предлагает context.getCacheDir и File.createTempFile для Java-приложений, я надеюсь, что на уровне C есть эквивалент.

Кто-нибудь знает о хорошем надежном и перекрестном методе Android для создания временного файла?

4b9b3361

Ответ 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;
}

Ответ 4

mkstemp доступен в NDK под stdlib.h

Ответ 5

  1. Получите путь к каталогу кэша при запуске приложения с помощью ContentProvider.
  2. Реализуйте функцию tmpfile с той же сигнатурой, что и в POSIX tmpfile.
  3. Вызовите mkstemp из функции tmpfile, используя ранее полученный каталог кеша

Упаковано как .aar, так что его можно использовать через gradle.

https://github.com/ViliusSutkus/tmpfile