You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Crashlytics捕获MediaPlayer相关ANR问题求助

排查Firebase Crashlytics捕获的MediaPlayer相关ANR问题

已通过Firebase Crashlytics捕获到以下ANR错误,该问题已困扰数月,现借助Crashlytics进一步排查成因,恳请协助:

ANR堆栈信息

main (native): tid=1 systid=7666 
#00 pc 0x9a4a4 libc.so (__ioctl + 8)
#01 pc 0x6754f libc.so (ioctl + 30)
#02 pc 0x2f1b5 libbinder.so (android::IPCThreadState::talkWithDriver(bool) + 228)
#03 pc 0x2ff39 libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*) + 36)
#04 pc 0x2fce3 libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int) + 134)
#05 pc 0x2a577 libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) + 118)
#06 pc 0x4291f libmedia.so (android::BpMediaPlayerService::create(android::sp<android::IMediaPlayerClient> const&, audio_session_t, android::content::AttributionSourceState const&) + 430)
#07 pc 0x38b69 libmedia.so (android::MediaPlayer::setDataSource(int, long long, long long) + 220)
#08 pc 0x50e3f libmedia_jni.so (android_media_MediaPlayer_setDataSourceFD(_JNIEnv*, _jobject*, _jobject*, long long, long long) + 146)
       at android.media.MediaPlayer._setDataSource(MediaPlayer.java)
       at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1354)
       at android.media.MediaPlayer.create(MediaPlayer.java:1047)
       at android.media.MediaPlayer.create(MediaPlayer.java:1015)
       at com.dev.myapp.activityone.playMediaPlayer(activityone.java:65)
       at com.dev.myapp.activityone$15.onFinish(activityone.java:10)
       at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:142)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8751)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

关联代码

public void playMediaPlayer(int id) {
        try {
            if (mediaPlayer != null || mediaPlayer.isPlaying()) {
                mediaPlayer.release();
                mediaPlayer = new MediaPlayer();
            }

            if (id == 1) {
                mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
            } else if (id == 2) {
                mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.sound2);

            }
            if (PreferenceData.getSound(getApplicationContext())) {
                mediaPlayer.start();
            }
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        }

    }

问题分析

  1. 主线程阻塞触发ANR:从堆栈可见,ANR发生在MediaPlayer.create执行阶段,该方法涉及与MediaPlayerService的跨进程(IPC)通信,在主线程执行时会阻塞UI线程,当IPC响应超时就会触发ANR。
  2. 资源管理逻辑漏洞:
    • 条件判断if (mediaPlayer != null || mediaPlayer.isPlaying())存在错误:若mediaPlayer为null,调用mediaPlayer.isPlaying()会直接抛出空指针异常;且后续new MediaPlayer()创建的实例会被MediaPlayer.create覆盖,造成不必要的资源泄漏。
    • 释放资源后未将mediaPlayer置为null,可能导致重复释放或空指针问题。
  3. 异常捕获不完整:仅捕获OutOfMemoryError,未处理MediaPlayer操作中常见的IllegalStateException等异常,可能导致线程异常阻塞。

修复方案

  1. 将MediaPlayer操作移至子线程:
    避免在主线程执行MediaPlayer.create等耗时IPC操作,使用子线程处理初始化和播放逻辑,示例如下:

    public void playMediaPlayer(int id) {
        new Thread(() -> {
            try {
                if (mediaPlayer != null) {
                    if (mediaPlayer.isPlaying()) {
                        mediaPlayer.stop();
                    }
                    mediaPlayer.release();
                    mediaPlayer = null;
                }
    
                if (id == 1) {
                    mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
                } else if (id == 2) {
                    mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.sound2);
                }
    
                if (mediaPlayer != null && PreferenceData.getSound(getApplicationContext())) {
                    mediaPlayer.start();
                    // 播放完成后自动释放资源
                    mediaPlayer.setOnCompletionListener(mp -> {
                        mp.release();
                        mediaPlayer = null;
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 异常后重置MediaPlayer
                if (mediaPlayer != null) {
                    mediaPlayer.release();
                    mediaPlayer = null;
                }
            }
        }).start();
    }
    
  2. 修正资源管理逻辑:

    • 移除多余的mediaPlayer = new MediaPlayer(),因为MediaPlayer.create会自动创建并初始化MediaPlayer实例。
    • 调整条件判断为if (mediaPlayer != null),先检查非空再处理播放状态和释放操作,释放后将mediaPlayer置为null。
  3. 完善异常捕获:
    将捕获范围扩大至Exception,覆盖MediaPlayer操作中的所有常见异常,避免未处理的异常导致线程阻塞或资源泄漏。

  4. 优化MediaPlayer复用(可选):
    若频繁播放少量固定音频,可提前初始化MediaPlayer实例并复用,减少重复创建和IPC调用次数,降低ANR风险。

内容的提问来源于stack exchange,提问作者Lechius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:20:43