ANdroid O MeidiaPlayer 深入理解(一)
前言
android對于java層的音頻播放器提供了很多api,主要的有 AudioTrack、SoundPool、MediaPlayer(其實(shí)AudioPlayer和MediaPlayerAdapter也都是加了AudioFcus后對于MediaPlayer的二次封裝,關(guān)于AudioFocus有時(shí)間再詳細(xì)介紹)。
其中AudioTrack主要是播放pcm流,而soundPool主要播放一些短暫的聲音,比如touch音。MediaPlayer主要播放媒體音頻文件像.mp3文件等。其中SoundPool和MediaPlayer最終都會在native層調(diào)用到audioTrack將音頻流寫入到對應(yīng)devices上。
關(guān)于MediaPlayer和AudioTrack的區(qū)別,這里就不細(xì)說了,百度一大堆。主要就是MediaPlayer會把.mp3等格式文件最終解析成pcm流輸出給audiotrack。關(guān)于MediaPlayer的Java層的各狀態(tài)轉(zhuǎn)化和各方法調(diào)用說明,這里也不一一細(xì)說了。度娘全是這玩意。
這里主要說說MediaPlayer關(guān)于native層的東東(本人java出生,對于c/c++等了解的難免疏漏,如有理解錯(cuò)誤,望各位大神不吝賜教,定虛心改正)。
MediaPlayer初始化
給大家提供一個(gè)免費(fèi)看源碼的網(wǎng)站(知道請略過)http://androidxref.com/
言歸正傳,就從java層的MediaPlayer說起吧。
MediaPlayer位于frameworks/base/media/java/android/media/下繼承PlayerBase。
其中PlayerBase的構(gòu)造方法如下:
MediaPlayer的構(gòu)造方法:
public MediaPlayer() {super(new AudioAttributes.Builder().build(),AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);Looper looper;if ((looper = Looper.myLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else if ((looper = Looper.getMainLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else {mEventHandler = null;}mTimeProvider = new TimeProvider(this);mOpenSubtitleSources = new Vector<InputStream>();/* Native setup requires a weak reference to our object.* It's easier to create it here than in C++.*/native_setup(new WeakReference<MediaPlayer>(this));baseRegisterPlayer();}可以看我們在使用時(shí)MediaPlayer時(shí),通過new MediaPlayer的方式到實(shí)際都做了什么,著重關(guān)注下這幾個(gè)點(diǎn)
1.new AudioAttributes.Builder()//這個(gè)主要后面的audioPolicy會用到。
2.native_setup
3.baseRegisterPlayer注冊了一個(gè)player狀態(tài)回調(diào),這塊邏輯,感興趣的可以自己查下源碼,暫忽略掉,有時(shí)間細(xì)看再補(bǔ)上這塊吧,今天重點(diǎn)不是他。
重點(diǎn)說2.native_setup,這步直接調(diào)用了jni方法,關(guān)于jni我了解不是很多,我主要做從事App開發(fā)的,底層的東東只能略知一二,說的不對的,請多多指教。
jni的加載主要通過 System.loadLibrary來實(shí)現(xiàn)的:
static {System.loadLibrary("media_jni");native_init();}在/frameworks/base/media/jni/android_media_MediaPlayer.cpp目錄下,這樣就走到了C++部分。
通過JNINativeMethod gMethods[]方法知道native_setup會調(diào)到android_media_MediaPlayer_native_setup方法。
其中:
static void android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) {ALOGV("native_setup");sp<MediaPlayer> mp = new MediaPlayer();if (mp == NULL) {jniThrowException(env, "java/lang/RuntimeException", "Out of memory");return;}// create new listener and give it to MediaPlayersp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);mp->setListener(listener);// Stow our new C++ MediaPlayer in an opaque field in the Java object.setMediaPlayer(env, thiz, mp); }Ok分析下sp<MediaPlayer> mp = new MediaPlayer(); native層的mediaplayer也有了,創(chuàng)建了一個(gè)C++的mediaPlayer對象。
繼續(xù):setMediaPlayer(env, thiz, mp)將創(chuàng)建的Native層的MediaPlayer對象保存到Java層。也就是說將來我們通過getMediaplayer()的時(shí)候獲取到的就是這個(gè)對象。
總結(jié)
到此MediaPlayer就創(chuàng)建完成了,通過java代碼 new MediaPlayer()開始,一直到native層創(chuàng)建native層的MediaPlayer,并將native層的MediaPlayer返回到j(luò)ava層,供java層調(diào)用。
其實(shí)整個(gè)MediaPlayer在運(yùn)行的時(shí)候,可以大致上分成Client和Server兩個(gè)部分,它們分別在兩個(gè)進(jìn)程中運(yùn)行,它們之間使用Binder機(jī)制實(shí)現(xiàn)IPC通訊,但Client端分一個(gè)在java層的MediaPlayer和native層的MediaPlayer。
最后感謝百度各位大師提供資料。
總結(jié)
以上是生活随笔為你收集整理的ANdroid O MeidiaPlayer 深入理解(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt5模型/视图结构-视图(View)
- 下一篇: 自己动手写js分享插件 [支持https