android Music 源码学习

转自http://blog.csdn.net/baimy1985/article/details/8244742#t0

1.音乐播放器代码结构


       Android源码的Music应用相关代码不算多,packages/apps/Music是关于UI界面的,\packages\providers\MediaProvider关于数据库的,数据库文件放在data/data/com.android.providers.media, 这里面有两个或更多个.db文件,external是外部数据库,记录着Music里显示的那些歌曲,internal是内部数据库,存放着系统铃声文件。根据sd的不同,每次.db文件名字也不同,一张sd卡对应的一个文件。代码方面只有com.android.music一个包,常用的几个类如下:

      几个关于列表显示的类,下面这些类的显示都用到track_list_item_common.xml这个布局文件,充分体现最大程度复用代码的原则。
      MusicBrowserActivity.java          主控制界面
      TrackBrowserActivity.java          音乐列表界面
      PlaylistBrowserActivity.java          播放列表界面
      AlbumBrowserActivity.java     专辑浏览界面
      ArtistAlbumBrowserActivity.java          艺术家浏览界面

      这两个应该是Music应用中最重要的类了,音乐播放器吗,没播放界面怎么行。
       MediaPlayerbackActivity.java          音乐播放界面
       MediaPlaybackService.java          音乐播放器服务

       下面这些都是对话框形式呈现出来的。
        RenamePlaylist.java          重命名播放列表界面
       CreatePlaylist.java          新建播放列表界面
       DeleteItems.java     删除提示框界面
       ScanningProgress.java          音乐描扫进度显示界面

       MediaAppWidgetProvider.java          Widget实现类
       MusicPicker.java          音乐选择界面,这是给其它应用程序调用的界面。
       MusicUtils.java          播放器公共方法类
       关于音乐Music,基本的东西就这些,仅从代码量上看,这算不上一个复杂的应用。如果只是想了解应用层的功能,上面这些不会花费太久的时间。让我们在往前走一走,这些歌曲是哪来的。

2. 扫描sdcard卡读取音乐文件


       准确的说应该是媒体文件的扫描,音乐只是其中的一部分。这部分主要包括mediaScannerService,Mediaprovider和MediaScannerReceiver三个类,开机的的时候会收到ACTION_BOOT_COMPLETED消息后启动内部存储扫描工作,而收到MEDIA_MOUNT会扫描SD卡。这里只是简单的说下的流程并不深入讨论,我们重点关心扫描后在把文件信息写到数据库的那个动作。如果仔细看MediaScanner.java的代码,会发现下面这段注释,

* Java MediaScannerService calls
* Java MediaScanner scanDirectories, which calls
* Java MediaScanner processDirectory (native method), which calls
* native MediaScanner processDirectory, which calls
* native MyMediaScannerClient scanFile, which calls
* Java MyMediaScannerClient scanFile, which calls
* Java MediaScannerClient doScanFile, which calls
* Java MediaScanner processFile (native method), which calls
* native MediaScanner processFile, which calls
* native parseMP3, parseMP4, parseMidi, parseOgg or parseWMA, which calls
* native MyMediaScanner handleStringTag, which calls
* Java MyMediaScanner handleStringTag.
* Once MediaScanner processFile returns, an entry is inserted in to the database.
       这个其实就是扫描的整个流程,在java与Native层反复切换,在上面第7行doScanFile方法后会有beginFile()和endFile();在endFile()方法中最后就是把扫描出来的信  息写入数据库,需要说明的是上面的注释针对是android 2.3的,在4.0的代码中有些方法找不到了,因为google采用stagefright来替换原来的opencore,(PS:借用百度出来结果  Opencore与stagefright两套机制,对于我们的开发而言,主要体现在parser和codec部分。最基本的实现,二者是相同的,可以共用,差别在封装上,opencore难度和工作量要大), 所以对于这一部分内容,如果想深入研究,不管是Opencore与stagefright,水还是挺深的。
 

  3. 如何播放音乐

      上面音乐也写到数据库了,也能列表显示,如何播放呢?
                    mMediaPlayer = new MediaPlayer();
                    mMediaPlayer.setDataSource(path);
                    mMediaPlayer.prepare();
                    mMediaPlayer.start();
       对于上层应用就是这样,new出MediaPlayer对象,设好路径,prepare()和start()就没事了,其它的都交给系统了,不过后面的事还是很多的,android的audio系统  也算比较复杂的一部分了。整个audio系统主要由负责输入AudioRecord、负责输出AudioTrack、负责混音的AudioFlinger和策略控制AudioPolicyService四个部分。
播放音乐的时候 setDataSourcet()、start()之后会在MediaPlayService的open函数创建AudioTack对象。AudioTrack的作用是要把它的数据发给对应的设备去输出(比如蓝牙耳机或扬声器),在输出之前它需要知道要找哪个设备,根据什么呢?根据流类型(STREAM_ALARM、STREAM_MUSIC、STREAM_RING、STREAM_SYSTEM和STREAM_VOICE_CALL)先找到对应的路由策略,这也是AudioPolicyService, AudioPolicyManagerBase存在的原因,再根据路由策略选择设备, 依据设备信息返回一个的线程索引号给  AudioTrack作为参数CreatTrack找到AudioFlinger合适工作线程(mixerThread or DupicatiingThread)来把数据发给对应的音频输出设备。整个过程还是蛮复杂的,这里只描述了大概流程。代码里面也是故事多多,想完全掌握需要花费些时间。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章