私の Android アプリケーション (minSdkLevel: 2.2、targetSdkLevel: 3.0、Android 4.2 を搭載した Nexus 7 でテスト) は、読み込みフェーズで次のことを行います。
- を作成し、その上に
SoundPoolを登録しますOnLoadCompleteListener - サウンドのロードを開始します。
SoundPoolサウンドが読み込まれるたびにコールバック メソッドを呼び出します。 - 読み込みプロセスがユーザーによって中断された場合、
SoundPool.release()呼び出されます - (
release()が既に呼び出されていて、以前に開始されたサウンドの読み込みが完了した場合、つまり、システムが my コールバックを呼び出した場合、アプリケーションは mySoundPoolが既に呼び出されていることを検出nullし、コールバックを無視するので安全です)。
Nexus 7 でテストすると、 SoundPool.release()(logcat) が呼び出さ
れてから 210 ミリ秒後に次のエラーが発生しました。
つまり、イベントの順序はおそらく次のとおりです。
SoundPool.load(...)私の呼び出しが原因で、システムがサウンドを非同期にロードし始めました- ローディング画面から出たので
SoundPool.release()呼び出されてSoundPoolセットnull - (?) システムは以前のサウンド読み込み完了コールバックを完了しましたが、何らかのエラーが発生しました。
AndroidソースコードとJNIコードを確認して、JNI経由でSoundPool.release()実際に削除します。弱い参照を使用して、Java レベルで参照を格納します。SoundPoolDeleteGlobalRefSoundPool
おそらく、非決定性のために正確な条件を再現できないため、バグを再現できません。システムは、非同期にサウンドをロードしている間にリリースされる可能性があることを正しく処理する必要SoundPoolがありますが、まれな状況でバグが発生するようです。(私のコードはSoundPoolnullcheck の後に正確に 1 回リリースされるので、エラーは確実に私のコードには含まれていないことに注意してください)。
Androidでこのようなエラーが発生する理由について何か考えはありますか? 理論的には、私の上記の疑いは正しいでしょうか? この Android バグからアプリケーションを保護するにはどうすればよいですか? たぶん、ブール値をSoundPool解放するように設定し、すべてのコールバックが返されるまで待ってから、最後のコールバックで (このブール値に基づいて) 解放することができますか? 他の回避策は考えられませんが、少なくともうまくいくことを確認したいと思います。