2012-06-08 9 views
12

Sto provando ad accedere alle risorse nel codice nativo da un WallpaperService personalizzato. Il codice nativo viene compilato e funziona, ma il tentativo di ottenere il riferimento AAssetManager dall'oggetto AssetManager passato alla funzione nativa restituisce sempre NULL.Impossibile accedere ad AAssetManager nel codice nativo passato da Java in WallpaperService

È qualcosa a che fare con il fatto che sto utilizzando un servizio piuttosto che un'attività che si traduce nel riferimento AAssetManager NULL? Nel sorgente Java, AssetManager passato alla funzione nativa è valido e non è nullo.

Per verificare questa li ho usati CubeLiveWallpaper demo dai campioni forniti e rivolte livello di API 10. Ecco il codice relativo aggiunto alla classe CubeWallpaper1 al fine di accedere alle funzionalità native:

static { 
    System.loadLibrary("renderer"); 
} 

private static native void load(AssetManager mgr); 

@Override 
public void onCreate() { 
    super.onCreate(); 

    AssetManager mgr = getResources().getAssets(); 
    load(mgr); 
} 

Ecco il codice JNI che sto usando per cercare di acquisire un riferimento AAssetManager valida:

#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"); 
    } 

} 

Questo è stato replicato su un paio di dispositivi, ma la maggior parte di test è stato fatto su un HTC Desire in esecuzione 2.3.7.

+0

La variabile mgr nel codice Java contiene qualcos'altro che null? –

+0

Sì, facendo un Log.v su 'mgr' nei report Java' android.content.res.AssetManager @ 405185e8' in DDMS. – cshaw

risposta

10

Leggere i commenti all'interno di asset_manager_jni.h: "Si noti che il chiamante è responsabile dell'ottenimento e della conservazione di un riferimento VM al jobject per impedire che venga raccolto automaticamente mentre l'oggetto nativo è in uso."

In Java, si passa un oggetto (mgr) che può essere liberato dal garbage collector una volta chiamato il callback nativo. Per evitare questo, si potrebbe, ad esempio, creare la variabile mons come un attributo privato nella classe e poi passare attraverso il metodo di carico, come ad esempio questo:

private static native void load(AssetManager mgr); 

private AssetManager mgr; 

@Override 
public void onCreate() { 
    super.onCreate(); 

    mgr = getResources().getAssets(); 
    load(mgr); 
} 

Inoltre, penso che è necessario sostituire il nativo Callback C++ con:

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

Successo! Il problema è stato causato dal non avere il parametro jobj obj nella dichiarazione del metodo JNI. E grazie anche per l'idea di dover mantenere un riferimento al jobject di AssetManager. – cshaw

+0

Come farlo usando SWIG? – Flayn

Problemi correlati