No se puede acceder a AAssetManager en código nativo pasado de Java en WallpaperService

Estoy intentando tener acceso a los activos en código nativo de un WallpaperService personalizado. El código nativo se compila y funciona, pero intenta obtener la referencia AAssetManager del objeto AssetManager pasado a la función nativa devuelve siempre NULL.

¿Tiene algo que ver con el hecho de que estoy utilizando un servicio en lugar de una actividad que resulta en la referencia AAssetManager que es NULL? En la fuente Java, AssetManager que se pasa a la función nativa es válido y no es nulo.

Para probar esto utilicé la demostración CubeLiveWallpaper de los ejemplos proporcionados y el API de nivel de orientación 10. Aquí está el código relevante añadido a la clase CubeWallpaper1 para acceder a la funcionalidad nativa:

static { System.loadLibrary("renderer"); } private static native void load(AssetManager mgr); @Override public void onCreate() { super.onCreate(); AssetManager mgr = getResources().getAssets(); load(mgr); } 

Aquí está el código JNI que estoy usando para intentar adquirir una referencia válida de AAssetManager:

 #include <jni.h> #include <android/log.h> #include <android/asset_manager.h> #include <android/asset_manager_jni.h> #define TAG "CubeWallpaper1.c" void Java_com_example_android_livecubes_cube1_CubeWallpaper1_load(JNIEnv *env, jobject assetManager) { AAssetManager *mgr = AAssetManager_fromJava(env, assetManager); if (mgr == NULL) { __android_log_print(ANDROID_LOG_ERROR, "CubeWallpaper1.c", "error loading asset maanger"); } else { __android_log_print(ANDROID_LOG_VERBOSE, "CubeWallpaper1.c", "loaded asset manager"); } } 

Esto se ha replicado en un par de dispositivos, pero la mayoría de las pruebas se ha realizado en un HTC Desire con 2.3.7.

Lea los comentarios dentro de asset_manager_jni.h: "Tenga en cuenta que la persona que llama es responsable de obtener y mantener una referencia de VM al jobject para evitar que se recoja basura mientras el objeto nativo está en uso."

En Java, está pasando un objeto (mgr) que puede ser liberado por el recolector de basura una vez que se llame la llamada nativa. Para evitar esto, podría, por ejemplo, crear la variable mgr como un atributo privado en su clase y luego pasarlo por el método de carga, como esto:

 private static native void load(AssetManager mgr); private AssetManager mgr; @Override public void onCreate() { super.onCreate(); mgr = getResources().getAssets(); load(mgr); } 

Además, creo que debe reemplazar su devolución de llamada nativa de C ++ con:

 void Java_com_example_android_livecubes_cube1_CubeWallpaper1_load (JNIEnv *env, jobject obj, jobject assetManager) 
  • Android poco convencional y desagradable durante el código de carga de JNI / OpenGL ES
  • No se pudo cargar la biblioteca libopencv_java.so
  • FindClass no puede encontrar la clase Java personalizada
  • CheckJNI de Android: ¿Cómo apagarlo / encender (en un emulador)? La documentación parece estar defectuosa
  • Camino de directorio de DCIM en Android - Valor de retorno
  • Firma de android apk con gradle-experimental: 0.2.0
  • Android-ndk Adición de bibliotecas estáticas al android.mk
  • Problema para crear NDK con C ++ en Android
  • Error de libcurl CURLE_SSL_CACERT_BADFILE en android
  • Android ndk (cmake): 'referencia indefinida a `__android_log_write' cuando se usa log api en la segunda biblioteca jni
  • Cómo pasar un mapa de bits de Java a C ++ con JNI en Android Development
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.