リクエストを作成し、サーバーから更新を受信する C スレッドがあります。更新は、JNI 呼び出しを介して Java に送信されます。私の問題は、最大 100 個のアイテムを含むプレイヤーのインベントリを受信したときに発生します (サーバーから 100 個の応答があり、この部分を変更できません)。問題が発生する場合と発生しない場合がありますが、在庫が大きいほど、この問題が発生する頻度が高くなります。
次のメッセージを除いて、logcat に例外はありません。
06-10 10:09:46.085: I/Choreographer(23815): Skipped 87 frames! The application may be doing too much work on its main thread.
そして、私のアプリが閉じます。runOnUiThread
また、アプリのクラッシュで UI を更新する行にコメントを付けても、それを言う必要があります。
JNI を使用して Java に戻ったときに UI スレッドにいるかどうかを確認しようとしましたがLooper.myLooper() == Looper.getMainLooper()
、false
.
誰も同じ問題を経験しましたか? C スレッドは何らかの形でメイン スレッドに関連していますか? ありがとう
編集
サーバーから更新を受信すると、次の呼び出しが行われます。
- Java スレッド (UI スレッドではない) から: という名前の C 関数を呼び出します。
notifyAll
From
notifyAll
call という名前の C 関数はupdate
、Java で同等のものを呼び出します (以下のコードを参照)。void UpdateListenerWrapper::update(Update& u) { // Retrieve the current JNIEnv* with the cached JVM int status; JNIEnv* env; bool isAttached = false; status = gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2); if(status < 0) { __android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to get JNI environment"); status = gCachedJVM->AttachCurrentThread(&env, NULL); if(status < 0) { __android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to attach current thread"); return; } isAttached = true; } jmethodID update = env->GetMethodID(gClazzUpdateListenerWrapper, "update", "(J)V"); // J stands for Java long type // Call Java method update from jUpdateListener object env->CallVoidMethod(jUpdateListener, update, (jlong)(intptr_t)&u); // Pointer as agument, we'll build the Update object in Java if (isAttached) { gCachedJVM->DetachCurrentThread(); } }
gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2);
問題はこの行にあり、おそらく GetEnv が UI スレッドのポインターを返すと思います。それが問題でしょうか?どうすればこれを修正できますか?