最近接觸到一些音頻開發(fā)的操作和一個音頻開發(fā)的三方庫:
github:https://github.com/Bilibili/ijkplayer虑稼。
有人會問為什么使用三方庫:最直接原因當然是因為系統(tǒng)的MediaPlayer支持格式不多或者是版本限制。具體只支持格式:
http://developer.android.com/intl/zh-cn/guide/appendix/media-formats.html
http://blog.csdn.net/ddna/article/details/5173481
而ijkplayer底層基于ffmpeg,這個是個超強大的庫喧半。這里據(jù)說一些視頻直播方案就是采用的該播放器箕速。
1. Gradle導入
# required
allprojects {
repositories {
jcenter()
}
}
dependencies {
# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.5.0'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.5.0'
# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.5.0'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.5.0'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.5.0'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.5.0'
# ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.5.0'
}
2. ijkplayer支持的操作:
首先可參見:MediaPlayer的文檔
http://developer.android.com/reference/android/media/MediaPlayer.html
1. 目前支持MediaPlayer的基本操作且參數(shù)一致如:
public native boolean isPlaying();
public native void seekTo(long msec) throws IllegalStateException;
public native long getCurrentPosition();
public native long getDuration();
public void pause() throws IllegalStateException
public void prepareAsync() throws IllegalStateException
public void start() throws IllegalStateException
這些方法位于IjkMediaPlayer類中零截,最終實現(xiàn)是由jni調用底層c++代碼锭汛。當然還有些高級用法,這里給大家同時挖個坑管呵,因為我也只使用了基本的功能梳毙。
2. 小坑:
MediaPlayer的isPlaying條件 : (1)playing 正在播放
ijkplayer的isPlaying 方法返回為true條件是: (1)prepare or (2)playing 正在播放
下面是c++源碼:
if (mp->mp_state == MP_STATE_PREPARED ||
mp->mp_state == MP_STATE_STARTED) {
return true;
}
3. CallBack 回調接口也是基本一致的。
interface OnPreparedListener {
void onPrepared(IMediaPlayer mp);
}
interface OnCompletionListener {
void onCompletion(IMediaPlayer mp);
}
interface OnBufferingUpdateListener {
void onBufferingUpdate(IMediaPlayer mp, int percent);
}
interface OnSeekCompleteListener {
void onSeekComplete(IMediaPlayer mp);
}
interface OnVideoSizeChangedListener {
void onVideoSizeChanged(IMediaPlayer mp, int width, int height,
int sar_num, int sar_den);
}
interface OnErrorListener {
boolean onError(IMediaPlayer mp, int what, int extra);
}
interface OnInfoListener {
boolean onInfo(IMediaPlayer mp, int what, int extra);
}
3. 特殊需求捐下,這個與player無關账锹。
1. 耳機插拔監(jiān)聽,比如耳機拔掉時關閉播放器坷襟〖榧恚可參考:
http://blog.csdn.net/thl789/article/details/7423523
2. 切換音頻源或播放其他資源時暫停等需求。
具體是實現(xiàn)AudioManager.OnAudioFocusChangeListener接口方法:
public void onAudioFocusChange(int focusChange)
繼續(xù)偷下懶婴程,就不在重復寫了廓奕。細節(jié)問題需要給位看官根據(jù)實際情形做決定:
http://www.reibang.com/p/32a67329307e
4 最近遇到的一個大坑:ANR
哎,沒遇到ANR Android程序猿的人生是不完整的排抬,最近使用0.4.5版時懂从,由于產(chǎn)品需要切換播放源授段,如果快速切換蹲蒲,就會造成ANR,主要原因是由于侵贵,切換是釋放資源我調用了其reset()届搁,該方法在主線程釋放資源超時。目前我看官方issue的建議是,重新new 一個ijkMeadiaPlayer卡睦,不調用reset宴胧,只調用release()方法。也有人提到使用在線程中reset表锻。 我的一個workaround是延遲執(zhí)行操作恕齐。
ps 另外一坑。
說起來也不算是坑瞬逊,ijkplayer不支持開播未prepared時显歧,seek進度。(據(jù)說是與ffmpeg有關确镊,不覺明歷)士骤。 讓且換播放源,同時能快進蕾域。
(1)看issue的一種workaroud是 延遲seek(主要說是由于seek的時機是在onPrepared以后)
(2)我的處理方式當然是在onPrepared以后再seek進度拷肌。