无法在 WallpaperService 中从 Java 传递的本机代码中访问 AAssetManager [英] Can't access AAssetManager in native code passed from Java in WallpaperService

查看:12
本文介绍了无法在 WallpaperService 中从 Java 传递的本机代码中访问 AAssetManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to access the the assets in native code from a custom WallpaperService. The native code compiles and works but trying to get the AAssetManager reference from the AssetManager object passed to the native function always returns NULL.

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

Is it something to do with the fact that I am using a Service rather than an Activity that results in the AAssetManager reference being NULL? In the Java source the AssetManager being passed to the native function is valid and is not null.

为了测试这一点,我使用了提供的示例中的 CubeLiveWallpaper 演示,并针对 API 级别 10.以下是添加到 CubeWallpaper1 类以访问本机功能的相关代码:

To test this I used them CubeLiveWallpaper demo from the samples provided and targeting API level 10. Here is the relevant code added to the CubeWallpaper1 class in order to access the native functionality:

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 代码:

Here is the JNI code I'm using to try and acquire a valid AAssetManager reference:

#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 上完成的.

This has been replicated on a couple of devices but most testing has been done on a HTC Desire running 2.3.7.

推荐答案

阅读asset_manager_jni.h里面的注释:请注意,调用者负责获取并持有一个对jobject的VM引用,以防止它被垃圾回收,而本机对象正在使用中."

Read the comments inside asset_manager_jni.h: "Note that the caller is responsible for obtaining and holding a VM reference to the jobject to prevent its being garbage collected while the native object is in use."

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

In Java, you are passing an object (mgr) that may be freed by the garbage collector once the native callback is called. To prevent this, you could, for example, create the mgr variable as a private attribute in your class and then pass it through the load method, such as this:

private static native void load(AssetManager mgr);

private AssetManager mgr;

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

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

另外,我认为您必须将本机 C++ 回调替换为:

Also, I think you must replace your native C++ callback with:

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

这篇关于无法在 WallpaperService 中从 Java 传递的本机代码中访问 AAssetManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆