一、问题排查

debug调试的framework日志信息:

根据日志,进入MediaPlayer的framework层看源码

STEP 1

先从

V/MediaPlayerNative: constructor
V/MediaPlayerNative: setListener

https://android.googlesource.com/platform/frameworks/av/+/master/media/libmedia/mediaplayer.cpp

可以看到这是正常的new了一个C++层的MediaPlayer

https://android.googlesource.com/platform/frameworks/base/+/56a2301/media/jni/android_media_MediaPlayer.cpp?autodive=0%2F%2F%2F%2F%2F

以及设置了一个Java层的弱引用给C++层的MediaPlayer监听,目前一切正常

STEP 2

再看后面的日志:

V/MediaPlayerNative: reset
......
V/MediaPlayerNative: setVideoSurfaceTexture
V/MediaPlayerNative: prepareAsync

https://android.googlesource.com/platform/frameworks/base/+/56a2301/media/jni/android_media_MediaPlayer.cpp?autodive=0%2F%2F%2F%2F%2F

可以看到这里对MediaPlayer的设置一切正常,没有异常。

包括后面通过url取获取HTTP流,以及获取大小都正常。

STEP 3

再看后面的日志:

V/PlayerBase: baseRelease() piid=679 state=1
......

https://android.googlesource.com/platform/frameworks/base/+/master/media/java/android/media/PlayerBase.java

发现MediaPlayer的父类PlayerBase居然被release了???

https://android.googlesource.com/platform/frameworks/base/+/master/media/java/android/media/MediaPlayer.java

STEP 4

可以看到,这是MediaPlayer被系统给GC了。

V/MediaPlayerNative: setListener
disconnect

https://android.googlesource.com/platform/frameworks/base/+/56a2301/media/jni/android_media_MediaPlayer.cpp?autodive=0%2F%2F%2F%2F%2F

可以看到,这里是最后C++层的MediaPlayer也做了release

二、原因分析

通过debug调试日志,可以分析出问题出在MediaPlayer被JVM的GC调用了finalize

三、解决办法

方案一

在调用MediaPlayer的prepareAsync后,开启一个异步延时线程,判断是否prepare成功,如果失败,则将MediaPlayer重置,在设置dataSource后再来一次prepare。

方案二

接入AOP框架,拦截MediaPlayer的finalize方法,在被GC系统调用前,记录状态改变。再做后续的重试处理。

考虑到AOP框架的大小,一般都上10M,如果考虑包体大小,可以采纳方案一,否则推荐方案二。

MediaPlayer的prepareAsync不回调onPrepared问题的更多相关文章

  1. Android(java)学习笔记180:Android MediaPlayer 播放prepareAsync called in state 8解决办法

    使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现.  第一种方法: private ...

  2. Android(java)学习笔记123:Android MediaPlayer 播放prepareAsync called in state 8解决办法

    1. 使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现.  第1种方法: priva ...

  3. 关于MediaPlayer的详细介绍

    1)如何获得MediaPlayer实例:可以使用直接new的方式:MediaPlayer mp = new MediaPlayer();也可以使用create的方式,如:MediaPlayer mp ...

  4. 使用SurfaceView和MediaPlayer实现视频做为背景

    场景:像我们在Uber应用开场,看到一一段视频作为開始.这样子让用户非常快投入应用使用的场景中去,这样的以视频作为开场的应用,我们是不是认为非常高大上呢,哈哈,事实上是使用了SerfaceView去载 ...

  5. 学习Android MediaPlayer

    Android Media Playback 原文 The Android multimedia framework includes support for playing variety of c ...

  6. Android开发之Mediaplayer

    Android提供了常见的音频.视频的编码.解码机制.借助于多媒体类MediaPlayer的支持,开发者能够非常方便在在应用中播放音频.视频.本篇博客主要解说在Android平台下怎样播放一个音频文件 ...

  7. Android--MP3播放器MediaPlayer

    前言 Android提供了常见的音频.视频的编码.解码机制.借助于多媒体类MediaPlayer的支持,开发人员可以很方便在在应用中播放音频.视频.本篇博客主要讲解在Android平台下如何播放一个音 ...

  8. Android 视频播放器 (二):使用MediaPlayer播放视频

    在 Android 视频播放器 (一):使用VideoView播放视频 我们讲了一下如何使用VideoView播放视频,了解了基本的播放器的一些知识和内容.也知道VideoView内部封装的就是Med ...

  9. Android MediaPlayer 基础简介

    本文链接: Android MediaPlayer 基础简介 简单介绍MediaPlayer的基本概念,状态,常用的方法与监听器. 什么是MediaPlayer MediaPlayer类可以用来播放音 ...

随机推荐

  1. linux命令之------Cat命令

    Cat命令 作用:cat命令用于连接文件并打印,查看文件内容: -n或--number:由1开始对所有输出的行数编号: -b或--number-nonblank:和-n相似,只不过对于空白行不做编号: ...

  2. 微信小程序知识云开发

    一个小程序最多5个服务类目,一个月可以修改3次类目 小程序侵权投诉的发起与应对 软件著作权作品登记证书 实现小程序支付功能 如何借助官方支付api简单.高效率地实现小程序支付功能 借助小程序云开发实现 ...

  3. QHUOJ - 1533: 计算组合数(大数计算)

    题目描述 给定两个正整数n,m,计算组合数C(n,m).组合数计算公式为:C(n,m)=n!/((n-m)!*m!) 已知n,m <= 50. 结果很大需要使用long long存储. 输入 输 ...

  4. (未完成)catalyst-system WriteUp(2019暑假CTF第一周reverse)

    目录 预备学习--Linux实践:ELF文件格式分析 一.概述 二.分析ELF文件头(ELF header) 三.通过文件头找到section header table,理解其内容 四.通过secti ...

  5. 第2课第7节_Java面向对象编程_内部类_P【学习笔记】

    摘要:韦东山android视频学习笔记  1.什么是内部类:在类的内部定义一个类,内部类可以访问类的私有属性 class Outer{ ; class Inner{ public void print ...

  6. PyCharm虚拟环(Project Interpreter)手动安装第三方包图解教程

    PyCharm虚拟环(Project Interpreter)手动安装第三方包图解教程 an鑫_wolfxin2010 关注 2018.03.13 21:58* 字数 313 阅读 3782评论 1喜 ...

  7. coredump之栈溢出

    1.栈溢出引发的core往往出现出现在递归调用中. gdb时看到的特征是: 栈缺失,当前栈地址不可读. 根据栈是逆向生长的特点(栈逆向生长,所以很容易出现类似数组溢出覆盖率函数返回地址,导致函数退出地 ...

  8. 备份数据库的shell

    #!/bin/bash #定义备份数据库名 dbname=yourdbname #定义备份数据库的用户名和密码 dbuser=yourdbuser dbpasswd=yourdbpasswd #数据库 ...

  9. 2018 python获取动态User-Agent

    from fake_useragent import UserAgent ua = UserAgent() headers = {'User-Agent': ua.random} print(ua.r ...

  10. Python3基础 dict __len__ 统计键值对的数量

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...