15

カスタムWallpaperServiceからネイティブコードのアセットにアクセスしようとしています。ネイティブコードはコンパイルされて機能しますが、ネイティブ関数に渡されたAssetManagerオブジェクトからAAssetManager参照を取得しようとすると、常にNULLが返されます。

AAssetManager参照がNULLになるアクティビティではなくサービスを使用しているという事実と関係がありますか?Javaソースでは、ネイティブ関数に渡されるAssetManagerは有効であり、nullではありません。

これをテストするために、提供されたサンプルからの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を実行しているHTCDesireで実行されています。

4

1 に答える 1

18

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

また、ネイティブC++コールバックを次のように置き換える必要があると思います。

void Java_com_example_android_livecubes_cube1_CubeWallpaper1_load
     (JNIEnv *env, jobject obj, jobject assetManager) 
于 2012-07-23T17:55:23.590 に答える