2012-06-08 23 views
12

Estoy intentando acceder a los activos en código nativo desde un WallpaperService personalizado. El código nativo se compila y funciona, pero tratar de obtener la referencia AAssetManager del objeto AssetManager pasado a la función nativa siempre devuelve NULL.No puedo acceder a AAssetManager en el código nativo pasado desde Java en WallpaperService

¿Tiene algo que ver el hecho de que estoy usando un Servicio en lugar de una Actividad que hace que la referencia de AAssetManager sea NULA? En la fuente de Java, el AssetManager que se pasa a la función nativa es válido y no es nulo.

Para probar esto he usado CubeLiveWallpaper demostración de las muestras proporcionadas y dirigidas a nivel de la API 10. Aquí está el código correspondiente añadió a la clase CubeWallpaper1 con el fin de 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í es el JNI código que estoy usando para tratar de adquirir una referencia válida 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 ha sido replicado en un par de dispositivos, pero la mayoría se han realizado pruebas en un HTC Desire funcionamiento 2.3.7.

+0

¿La variable de mgr en el código de Java contiene algo más que nulo? –

+0

Sí, haciendo un Log.v en 'mgr' en informes de Java' android.content.res.AssetManager @ 405185e8' en DDMS. – cshaw

Respuesta

10

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 proyecto de trabajo para evitar que se recolecte 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 llama a la devolución de llamada nativa. Para evitar esto, se podía, por ejemplo, crear la variable mgr como un atributo privado en su clase y luego pasarla a través del método de carga, como este:

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 hay que reemplazar su nativa C++ devolución de llamada con:

void Java_com_example_android_livecubes_cube1_CubeWallpaper1_load 
    (JNIEnv *env, jobject obj, jobject assetManager) 
+0

¡Éxito! El problema fue causado por no tener el objectject obj param en la declaración del método JNI. Y gracias por el aviso también sobre la necesidad de mantener una referencia al proyecto de trabajo de AssetManager. – cshaw

+0

¿Cómo hacer esto usando SWIG? – Flayn

Cuestiones relacionadas