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

Android应用中USB存储连接时MediaPlayer的onCompletion()被意外调用的问题修复求助

Android应用中USB存储连接时MediaPlayer的onCompletion()被意外调用的问题修复求助

嘿,看起来你遇到了一个挺恼人的问题——USB存储一连接到设备,正在播放的视频明明还没结束,MediaPlayer的onCompletion()却被直接触发了对吧?我来帮你分析下可能的原因,再给出针对性的解决办法。

可能的原因

这种情况通常是因为USB连接时,系统会触发存储挂载/扫描操作,导致MediaPlayer正在读取的视频文件路径暂时不可用;或者你的USB文件更新逻辑间接干扰了MediaPlayer的播放状态,让它误以为播放已经完成。

具体解决方案

1. 在onCompletion()中添加播放状态校验

先判断MediaPlayer是否真的播放完毕,过滤掉意外触发的回调:

override fun onCompletion(mp: MediaPlayer?) {
    // 留1秒左右的误差,避免因为播放进度的微小偏差误判
    val isActuallyCompleted = mp?.let { 
        !it.isPlaying && it.currentPosition >= it.duration - 1000 
    } ?: false

    if (isActuallyCompleted) {
        // 这里放你原来的播放完成处理逻辑
    } else {
        // 属于意外触发,尝试恢复播放或者忽略
        mp?.start()
    }
}

2. 检查onDownloadFinished()的逻辑是否干扰MediaPlayer

你的PlayerViewModel实现了USBDownloadListener,在onDownloadFinished()里的代码会不会间接停止或释放了MediaPlayer?比如有没有调用mediaPlayer.stop()、mediaPlayer.release()这类方法?如果有的话,需要调整这部分逻辑,确保USB文件更新时不会影响正在播放的视频。

3. 监听USB挂载/卸载事件,提前保护MediaPlayer

在USBIOManager的广播接收器里区分USB动作,提前暂停/恢复MediaPlayer,避免它因为数据源中断触发异常:

override fun onReceive(context: Context, intent: Intent) {
    when(intent.action) {
        Intent.ACTION_MEDIA_UNMOUNTED -> {
            // USB即将卸载,先暂停播放
            (downloadListener as? PlayerViewModel)?.pausePlayback()
        }
        Intent.ACTION_MEDIA_MOUNTED -> {
            // USB挂载完成,更新文件后恢复播放
            updateUSBFiles(context)
            (downloadListener as? PlayerViewModel)?.resumePlayback()
        }
        // 处理其他USB相关动作
    }
}

然后在PlayerViewModel中添加对应的暂停/恢复方法:

private var mediaPlayer: MediaPlayer? = null // 假设你持有MediaPlayer实例

fun pausePlayback() {
    mediaPlayer?.takeIf { it.isPlaying }?.pause()
}

fun resumePlayback() {
    mediaPlayer?.takeIf { !it.isPlaying }?.start()
}

4. 利用OnErrorListener捕获存储异常

你的ViewModel已经实现了MediaPlayer.OnErrorListener,可以在这里处理因USB连接导致的IO错误,避免触发onCompletion():

override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean {
    // 捕获IO类错误(通常是文件路径不可用)
    if (what == MediaPlayer.MEDIA_ERROR_IO) {
        try {
            // 尝试重置MediaPlayer并重新加载视频
            mp?.reset()
            mp?.setDataSource(yourVideoFilePath) // 替换成你的视频路径
            mp?.prepare()
            mp?.start()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return true // 返回true表示已处理错误,不会触发onCompletion
    }
    return false
}

你可以先从检查onDownloadFinished()的逻辑开始,再逐步尝试上面的方案,应该能解决这个问题。

备注:内容来源于stack exchange,提问作者jpskgc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 12:53:03