2012-06-08 2 views
12

Я пытаюсь получить доступ к активам в собственном коде из пользовательского WallpaperService. Собственный код компилируется и работает, но попытка получить ссылку AAssetManager из объекта AssetManager, переданного в нативную функцию, всегда возвращает NULL.Невозможно получить доступ к AAssetManager в собственном коде, переданном из Java в WallpaperService

Это связано с тем, что я использую службу, а не активность, которая приводит к тому, что ссылка AAssetManager равна NULL? В источнике Java AssetManager, передаваемый в нативную функцию, действителен и не является нулевым.

Чтобы проверить это, я использовал их CubeLiveWallpaper демо из полученных образцов и ориентированных на уровень API 10. Здесь соответствующий код добавляется к классу CubeWallpaper1 для того, чтобы получить доступ к родной функциональности:

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

private static native void load(AssetManager mgr); 

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

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

Вот является JNI код, я использую, чтобы попытаться получить действительную ссылку 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"); 
    } 

} 

Это было воспроизведено на нескольких устройствах, но большинство испытаний было сделано на HTC Desire под управлением 2.3.7.

+0

Имеет ли переменная mgr в коде Java что-то еще, кроме нуля? –

+0

Да, делая Log.v на 'mgr' в Java-отчетах' android.content.res.AssetManager @ 405185e8' в DDMS. – cshaw

ответ

10

Прочитать комментарии в файле asset_manager_jni.h: «Обратите внимание, что вызывающий объект отвечает за получение и хранение ссылки VM на задание, чтобы предотвратить сбор мусора, когда нативный объект используется».

В Java вы передаете объект (mgr), который может быть освобожден сборщиком мусора после вызова нативного вызова. Чтобы предотвратить это, вы можете, например, создать переменную MGR в качестве частного атрибута в классе, а затем передать его через метод загрузки, например, следующим образом:

private static native void load(AssetManager mgr); 

private AssetManager mgr; 

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

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

Кроме того, я думаю, вы должны заменить родной C++ обратный вызов с:

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

Успех! Проблема была вызвана тем, что в объявлении метода JNI не было параметра obj jobject. И спасибо за то, что хедз-а также слишком нуждаются в том, чтобы ссылаться на задание AssetManager. – cshaw

+0

Как это сделать с помощью SWIG? – Flayn

Смежные вопросы