无法在WallpaperService中从Java传递的本机代码中访问AAssetManager

csh*_*haw 14 java-native-interface android android-ndk

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

是否与我使用服务而不是活动导致AAssetManager引用为NULL的事实有关?在Java源代码中,传递给本机函数的AssetManager是有效的,不是null.

为了测试这个,我在提供的示例和目标API级别10中使用了CubeLiveWallpaper演示.以下是为了访问本机功能而添加到CubeWallpaper1类的相关代码:

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

private static native void load(AssetManager mgr);

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

    AssetManager mgr = getResources().getAssets();
    load(mgr);
}
Run Code Online (Sandbox Code Playgroud)

这是我用来尝试获取有效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");
    }

}
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*ani 16

阅读asset_manager_jni.h中的注释:"请注意,调用者负责获取并保存对作业的VM引用,以防止在使用本机对象时对其进行垃圾回收."

在Java中,您传递的对象(mgr)可能会在调用本机回调后被垃圾回收器释放.为了防止这种情况,您可以,例如,将mgr变量创建为类中的私有属性,然后将其传递给load方法,例如:

private static native void load(AssetManager mgr);

private AssetManager mgr;

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

  mgr = getResources().getAssets();
  load(mgr);
}
Run Code Online (Sandbox Code Playgroud)

此外,我认为您必须用以下内容替换您的本机C++回调:

void Java_com_example_android_livecubes_cube1_CubeWallpaper1_load
     (JNIEnv *env, jobject obj, jobject assetManager) 
Run Code Online (Sandbox Code Playgroud)