一、問題排查
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
以及設置了一個Java層的弱引用給C++層的MediaPlayer監聽,目前一切正常
STEP 2
再看后面的日志:
V/MediaPlayerNative: reset
......
V/MediaPlayerNative: setVideoSurfaceTexture
V/MediaPlayerNative: prepareAsync
可以看到這里對MediaPlayer的設置一切正常,沒有異常。
包括后面通過url取獲取HTTP流,以及獲取大小都正常。
STEP 3
再看后面的日志:
V/PlayerBase: baseRelease() piid=679 state=1
......
發現MediaPlayer的父類PlayerBase居然被release了???
STEP 4
可以看到,這是MediaPlayer被系統給GC了。
V/MediaPlayerNative: setListener
disconnect
可以看到,這里是最后C++層的MediaPlayer也做了release
二、原因分析
通過debug調試日志,可以分析出問題出在MediaPlayer被JVM的GC調用了finalize。
三、解決辦法
方案一
在調用MediaPlayer的prepareAsync后,開啟一個異步延時線程,判斷是否prepare成功,如果失敗,則將MediaPlayer重置,在設置dataSource后再來一次prepare。
方案二
接入AOP框架,攔截MediaPlayer的finalize方法,在被GC系統調用前,記錄狀態改變。再做后續的重試處理。
考慮到AOP框架的大小,一般都上10M,如果考慮包體大小,可以采納方案一,否則推薦方案二。