MediaPlayer的prepareAsync不回調onPrepared問題


一、問題排查

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,如果考慮包體大小,可以采納方案一,否則推薦方案二。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM