0

C++からのGPSローカリゼーションを有効にするための呼び出しに問題があります。SWIGを使用してJNIラッパーを生成しました。logcatは言う:

01-02 17:14:03.816: D/dalvikvm(6165): Trying to load lib /data/data/com.example.swig/lib/libcppinterface.so 0x44e7ebf0
01-02 17:14:03.976: D/dalvikvm(6165): Added shared lib /data/data/com.example.swig/lib/libcppinterface.so 0x44e7ebf0
01-02 17:14:04.886: W/dalvikvm(6165): JNI WARNING: 0x44e8bb48 is not a valid JNI reference
01-02 17:14:04.886: W/dalvikvm(6165):              in Lcom/example/swig/cpplib/cppinterfaceJNI;.LocationSpotter_refresh (JLcom/example/swig/cpplib/LocationSpotter;)V (CallVoidMethodV)
01-02 17:14:04.886: I/dalvikvm(6165): "main" prio=5 tid=1 RUNNABLE
01-02 17:14:04.886: I/dalvikvm(6165):   | group="main" sCount=0 dsCount=0 s=N obj=0x4001d8e0 self=0xccb0
01-02 17:14:04.886: I/dalvikvm(6165):   | sysTid=6165 nice=0 sched=0/0 cgrp=default handle=-1345026008
01-02 17:14:04.886: I/dalvikvm(6165):   | schedstat=( 226108400 549900071 66 )
01-02 17:14:04.886: I/dalvikvm(6165):   at com.example.swig.cpplib.cppinterfaceJNI.LocationSpotter_refresh(Native Method)
01-02 17:14:04.896: I/dalvikvm(6165):   at com.example.swig.cpplib.LocationSpotter.refresh(LocationSpotter.java:56)
01-02 17:14:04.896: I/dalvikvm(6165):   at com.example.swig.MainActivity.onCreate(MainActivity.java:50)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.os.Handler.dispatchMessage(Handler.java:99)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.os.Looper.loop(Looper.java:123)
01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.main(ActivityThread.java:4627)
01-02 17:14:04.896: I/dalvikvm(6165):   at java.lang.reflect.Method.invokeNative(Native Method)
01-02 17:14:04.896: I/dalvikvm(6165):   at java.lang.reflect.Method.invoke(Method.java:521)
01-02 17:14:04.896: I/dalvikvm(6165):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
01-02 17:14:04.896: I/dalvikvm(6165):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
01-02 17:14:04.896: I/dalvikvm(6165):   at dalvik.system.NativeStart.main(Native Method)
01-02 17:14:04.906: E/dalvikvm(6165): VM aborting

この行でJavaからの呼び出しをトリガーします:

LocationSpotter.getLocationSpotter().refresh();

getLocationSpotter()は、C ++で、ジョブジェクト(jSpotter)を作成するこのコードをトリガーします。

// Retrieve the current JNIEnv* with the cached JVM
JNIEnv* env;
AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);

jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");
jmethodID construct = env->GetMethodID(clazz, "<init>", "()V");

jSpotter = env->NewObject(clazz, construct);

そして、メソッドrefresh()がこのコードをトリガーした後、アプリケーションがクラッシュします。

// Retrieve the current JNIEnv* with the cached JVM
JNIEnv* env;
AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);

jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");
jmethodID refresh = env->GetMethodID(clazz, "refresh", "()V");

env->CallVoidMethod(jSpotter, refresh); // The line where the crash happens

また、JNI_OnLoad関数で「cachedJVM」を開始することにも言及する必要があります。誰かがこれについて私を助けてくれることを願っています、ありがとう

編集

作業コード:

// Retrieve the current JNIEnv* with the cached JVM
JNIEnv* env;
AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);

jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");
jmethodID construct = env->GetMethodID(clazz, "<init>", "()V");

jSpotter = env->NewObject(clazz, construct);

jSpotter = env->NewGlobalRef(jSpotter);
4

1 に答える 1

1

返された参照を使用して、新しいグローバル参照を作成する必要がありますjSpotter。現在使用している参照は現在のフレームに対してローカルであり、スコープ外になります(おそらく、DetachCurrentThread()を使用する場合)。

env->NewGlobalRef(jSpotter)またはenv->NewWeakGlobalRef(jSpotter)(どちらにも対応する関数があります)を呼び出しfreeて、返された参照を使用する必要があります。

編集

適切なアタッチ/デタッチ処理の例を次に示します(Java操作をさらに行うためにスレッドが必要ないと仮定します)。

  JNIEnv* env;
  JavaVM* jvm = AndroidLocationSpotter::cachedJVM;

  int attached = jvm->GetEnv((void *)&env, JNI_VERSION_1_4) == JNI_OK;
  if (!attached) {
    if (jvm->AttachCurrentThread((void *)&env, NULL) != JNI_OK) {
      // Attach failed, handle error condition
      return;
    }
  }

  // Pushing a frame ensures proper cleanup of any local references you might generate
  // in your JNI code, e.g. with NewLocalRef (optional)                                                                                                                                                                                
  if (env->PushLocalFrame(16) < 0) {
    // Handle failed frame push error
  }
  else {
    // example local reference generation: ref2 = env->NewLocalRef(ref);

    //
    // Perform your primary Java operations here
    //

    env->PopLocalFrame(NULL);
  }

  if (!attached) {
    jvm->DetachCurrentThread();
  }
于 2013-01-02T21:23:08.533 に答える