2011-09-29 13 views
18

Actualmente estoy trabajando en una aplicación de Android basada en NDK basada en C. Esta aplicación necesita crear archivos temporales. En un sistema Linux normal, usaría tmpfile para asegurarme de que estos archivos se crean correctamente en un directorio temporal y se limpian al final del proceso.Creación de archivos temporales en Android con NDK

Sin embargo, mis investigaciones sobre diversos dispositivos Android parecen indicar que

  • tmpfile siempre falla;
  • no hay directorio /tmp;
  • El directorio /data/local/tmp no está presente en todas las variantes de Android;
  • no hay TEMP conjunto de variables de entorno;
  • mkstemp no funciona mejor que tmpfile.

ahora, estoy seguro de que podría hackear algo juntos, pero al ver que el SDK ofrece context.getCacheDir y File.createTempFile para aplicaciones Java, espero que no existe un equivalente en C-nivel.

¿Alguien sabe de un buen método confiable y cruzado de Android para crear un archivo temporal?

Respuesta

9

La mejor manera que hemos encontrado es llamar al Context.getCacheDir en el inicio, obtener su ruta con getAbsolutePath, luego llamar a una función JNI para almacenar esa ruta en un global. Cualquier función que quiera crear un archivo temporal simplemente agrega un nombre de archivo temporal adecuado a esa ruta.

Si realmente quiere buscarla a JNI Otra alternativa sería que pasar en un Context a una función JNI y el uso de un montón de GetMethodID/CallObjectMethod cosas para llamar de nuevo en Java para getCacheDir, pero el primer enfoque es mucho más simple.

Lamentablemente, no parece haber una solución más elegante en este momento.

+2

Es posible utilizar 'libcore' para llamar a' setenv() ', ver http://stackoverflow.com/a/22315463/192373. Esta puede ser una forma más elegante de mostrar el nombre del directorio de caché a nativo. –

0

mkstemp está disponible en el NDK bajo stdlib.h

+0

¿Esto ayuda? Creo que mkstemp consume una 'plantilla' que contiene la ruta completa a un directorio temporal. –

2

continuación es el procedimiento GetMethodID/CallObjectMethod que Ertebølle refiere a. Es necesario si está trabajando con una aplicación nativa pura (como la desarrollada por Visual Studio 2015) y no puede usar el código de 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; 
}