15

我正在尝试从自定义 WallpaperService 访问本机代码中的资产。本机代码编译并工作,但尝试从传递给本机函数的 AssetManager 对象获取 AAssetManager 引用始终返回 NULL。

这与我使用服务而不是导致 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);
}

这是我用来尝试获取有效 AAssetManager 参考的 JNI 代码:

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

}

这已经在几台设备上进行了复制,但大多数测试都是在运行 2.3.7 的 HTC Desire 上完成的。

4

1 回答 1

18

阅读asset_manager_jni.h 中的注释:“请注意,调用者负责获取并持有对jobject 的VM 引用,以防止在使用本机对象时对其进行垃圾收集。”

在 Java 中,您正在传递一个对象 (mgr),一旦调用本机回调,垃圾收集器就可以释放该对象 (mgr)。为了防止这种情况,例如,您可以在类中创建 mgr 变量作为私有属性,然后通过 load 方法将其传递,例如:

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) 
于 2012-07-23T17:55:23.590 回答