摘要:其中和最終都會在層調用到將音頻流寫入到對應上。關于和的區別,這里就不細說了,百度一大堆。繼續將創建的層的對象保存到層。最后感謝百度各位大師提供資料。
前言
android對于java層的音頻播放器提供了很多api,主要的有 AudioTrack、SoundPool、MediaPlayer(其實AudioPlayer和MediaPlayerAdapter也都是加了AudioFcus后對于MediaPlayer的二次封裝,關于AudioFocus有時間再詳細介紹)。
其中AudioTrack主要是播放pcm流,而soundPool主要播放一些短暫的聲音,比如touch音。MediaPlayer主要播放媒體音頻文件像.mp3文件等。其中SoundPool和MediaPlayer最終都會在native層調用到audioTrack將音頻流寫入到對應devices上。
關于MediaPlayer和AudioTrack的區別,這里就不細說了,百度一大堆。主要就是MediaPlayer會把.mp3等格式文件最終解析成pcm流輸出給audiotrack。關于MediaPlayer的Java層的各狀態轉化和各方法調用說明,這里也不一一細說了。度娘全是這玩意。
這里主要說說MediaPlayer關于native層的東東(本人java出生,對于c/c++等了解的難免疏漏,如有理解錯誤,望各位大神不吝賜教,定虛心改正)。
給大家提供一個免費看源碼的網站(知道請略過)http://androidxref.com/
言歸正傳,就從java層的MediaPlayer說起吧。
構造方法
MediaPlayer位于frameworks/base/media/java/android/media/下繼承PlayerBase。
其中PlayerBase的構造方法如下:
PlayerBase(@NonNull AudioAttributes attr, int implType) { if (attr == null) { throw new IllegalArgumentException("Illegal null AudioAttributes"); } mAttributes = attr; mImplType = implType; mState = AudioPlaybackConfiguration.PLAYER_STATE_IDLE; };
MediaPlayer的構造方法:
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(); /* Native setup requires a weak reference to our object. * It"s easier to create it here than in C++. */ native_setup(new WeakReference (this)); baseRegisterPlayer(); }
可以看我們在使用時MediaPlayer時,通過new MediaPlayer的方式到實際都做了什么,著重關注下這幾個點
1.new AudioAttributes.Builder()//這個主要后面的audioPolicy會用到。
2.native_setup
3.baseRegisterPlayer注冊了一個player狀態回調,這塊邏輯,感興趣的可以自己查下源碼,暫忽略掉,有時間細看再補上這塊吧,今天重點不是他。
重點說2.native_setup,這步直接調用了jni方法,關于jni我了解不是很多,我主要做從事App開發的,底層的東東只能略知一二,說的不對的,請多多指教。
private native final void native_setup(Object mediaplayer_this);
jni的加載主要通過 System.loadLibrary來實現的:
static { System.loadLibrary("media_jni"); native_init(); }
在/frameworks/base/media/jni/android_media_MediaPlayer.cpp目錄下,這樣就走到了C++部分。
通過JNINativeMethod gMethods[]方法知道native_setup會調到android_media_MediaPlayer_native_setup方法。
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
其中:
static void android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) { ALOGV("native_setup"); spmp = new MediaPlayer(); if (mp == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); return; } // create new listener and give it to MediaPlayer sp 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
繼續:setMediaPlayer(env, thiz, mp)將創建的Native層的MediaPlayer對象保存到Java層。也就是說將來我們通過getMediaplayer()的時候獲取到的就是這個對象。
到此MediaPlayer就創建完成了,通過java代碼 new MediaPlayer()開始,一直到native層創建native層的MediaPlayer,并將native層的MediaPlayer返回到java層,供java層調用。
其實整個MediaPlayer在運行的時候,可以大致上分成Client和Server兩個部分,它們分別在兩個進程中運行,它們之間使用Binder機制實現IPC通訊,但Client端分一個在java層的MediaPlayer和native層的MediaPlayer。
最后感謝百度各位大師提供資料。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77219.html
摘要:方法即為收集器,它接收高階函數和的后端掘金年的第一天,我坐在獨墅湖邊,寫下這篇文章。正因如此,所以最全系列教程后端掘金是從版本開始引入的一個新的,可以替代標準的。 設計模式之單例模式 - 掘金前言 作為一個好學習的程序開發者,應該會去學習優秀的開源框架,當然學習的過程中不免會去閱讀源碼,這也是一個優秀程序員的必備素養,在學習的過程中很多人會遇到的障礙,那就是設計模式。很多優秀的框架會運...
摘要:谷歌表示,與搜索并列,是谷歌機器學習技術最重要的產品服務載體。谷歌宣布了基于機器學習技術的全面升級,很可能是其誕生以來的最大升級。在去年的大會上,谷歌宣布了其第一代。 showImg(https://segmentfault.com/img/bVNTKT?w=900&h=385); Google I/O Google I/O 是由 Google 舉行的網絡開發者年會,討論的焦點是用 G...
閱讀 1645·2021-10-09 09:44
閱讀 2814·2021-10-08 10:04
閱讀 2478·2021-09-26 09:55
閱讀 3859·2021-09-22 10:02
閱讀 3317·2019-08-29 17:08
閱讀 1075·2019-08-29 15:08
閱讀 2963·2019-08-26 13:52
閱讀 3281·2019-08-26 13:34