android6.0 源码 系统应用之Music代码之类逻辑分析

本文解析了一款音乐应用的架构设计,介绍了多个关键组件的功能及其实现方式,包括音乐播放、预览、播放列表管理和音量控制等功能。文章还详细探讨了AudioFocus的申请与释放流程及其在不同场景下的应用。

共勉----不积跬步,无以至千里。

1. AlbumBrowserActivity此类继承自ListActivity实现接口 View.OnCreateContextMenuListener,   MusicUtils.Defs,    ServiceConnection该类的作用是显示专辑的界面。

2.ArtistAlbumBrowserActivity此类继承ExpandableListActivity实现接口 View.OnCreateContextMenuListener, MusicUtils.Defs, ServiceConnection该类的作用是显示艺术家列表,内部是ExpandableList。

**3.AudioPreview此类继承自Activity实现接口OnPreparedListener, OnErrorListener, OnCompletionListener此类提供界面当其他程序如文件管理器要加入音乐时提供音乐预览的界面。

onCreate

1、获取intent,获取传递过来的data(uri)

2、关联布局

3、关联控件

4、初始化AudioManager、PreviewPlayer(extends MediaPlayer)

PreviewPlayer player = (PreviewPlayer) getLastNonConfigurationInstance();

设置播放音乐文件的路径:mPlayer.setDataSourceAndPrepare(mUri);

初始化进度条

onStart

      1、注册对于音频输出的监控广播:AudioManager.ACTION_AUDIO_BECOMING_NOISY

接收到时对音乐做暂停操作

      2、再对亮屏和灭屏做广播监听如下

registerReceiver(mScreenTimeoutListener, new IntentFilter(s));

onResume:

    1、让进度条开始滚动:

mProgressRefresher.removeCallbacksAndMessages(null);

mProgressRefresher.post(new ProgressRefresher());

2、使屏幕保持常亮:

PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);

wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "MyTag");

wl.acquire();

方法中获取了 SCREEN_DIM_WAKE_LOCK锁,该锁使 CPU 保持运转,屏幕保持亮度(可以变灰)。这个函数在Activity的 onResume中被调用。

onStop、onDestory:

其中做的操作主要就是对上边创建的广播的注销,以及一些资源的释放(MediaPlayer、wakeLock、进度条的Handler)

****

介绍一下AudioFocus的申请和释放

 一、申请和释放

1、申请则为:requestAudioFocus()

2、释放则为:abandonAudioFocus()

二、过程

如代码中:

 

申请过程

1、获取AudioManager对象

mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

2、AudioFocus的申请

mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

 

*注释:其中参数为1、监听如下图 2、流类型(音频类型)streamType

2、① AUDIOFOCUS_GAIN 指申请的AudioFocus申请的不知道会持续多久,一般是长期占有 ② AUDIOFOCUS_GAIN_TRANSILENT 是指申请的AudioFocus是暂时性的,会很快用完释放

③AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK申请的AudiFocus是暂时性的,还指当前的AudioFocus可以继续播放,只要duck一下(降低音量)4、申请AudioFocus监听成功后,后续如果有别的程序竞争AudioFocus,都是通过Listeneer的onAudioFocusChange()方法来通知这个AudioFocus的使用者的

3、监听中对应的不同情况

·  AUDIOFOCUS_GAIN:获得了Audio Focus;

·  AUDIOFOCUS_LOSS:失去了Audio Focus,并将会持续很长的时间。这里因为可能会停掉很长时间,所以不仅仅要停止Audio的播放,最好直接释放掉Media资源。而因为停止播放 Audio的时间会很长,如果程序因为这个原因而失去AudioFocus,最好不要让它再次自动获得AudioFocus而继续播放,不然突然冒出来的 声音会让用户感觉莫名其妙,感受很不好。这里直接放弃AudioFocus,当然也不用再侦听远程播放控制。要再次播放,除非用户再 在界面上点击开始播放,才重新初始化Media,进行播放。

·  AUDIOFOCUS_LOSS_TRANSIENT:暂时失去Audio Focus,并会很快再次获得。必须停止Audio的播放,但是因为可能会很快再次获得AudioFocus,这里可以不释放Media资源;

·  AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暂时失去AudioFocus,但是可以继续播放,不过要在降低音量。

4、播放->抢占->再次获取

· AudioFocus Client通过requestAudioFocus()获取AudioFocus,在获得AudioFocus之后,开始播放Audio[Step#1 ~ #2];

· 其它程序(Other App)也通过requestAudioFocus()获取同类AudioStream的AudioFocus [Step#3]

· AudioFocus Client失去了Audio Focus,在onAudioFocusChanged()中,根据focusChange的值,做第二节中的处理[Step#4];

· 其它程序(Other App)获取Audio Focus之后,开始播放Audio[Step#5];

· 其它程序(Other App)使用Audio之后,通过abandonAudioFocus()归还AudioFocus [Step#6];

· AudioFocus Client重新获得了Audio Focus,可做进一步的处理 [Step#7]

 

4.CheckableRelativeLayout此类继承自RelativeLayout实现接口Checkable,这是一个自定义的布局

5.CreatePlaylist此类继承自Activity该类提供创建播放列表的界面

6.DeleteItems此类继承自Activity该类提供删除音乐时的提示界面主题是Dialog

7.MediaAppWidgetProvider此类继承自AppWidgetProvider,其作用是实现桌面的音乐插件

8.MediaButtonIntentReceiver此类继承自BroadcastReceiver,此类提供对相应蓝牙耳机的按钮按下发送的广播进行接收的机制

9.MediaPickerActivity此类继承自ListActivity实现接口MusicUtils.Defs

**10.MediaPlaybackActivity此类继承自Activity实现接口MusicUtils.Defs,  View.OnTouchListener,  View.OnLongClickListener该类提供音乐播放的界面,用户在该界面上可以点击控制音乐的播放,暂停,前进和后退。

//如果歌播放超过1秒,点击播放歌曲上一首,播放当前歌曲的开始处。

长按的话就会是上一首歌的效果。

 

onCreate

   1、对播放音乐文件能用音量键控制 setVolumeControlStream(AudioManager.STREAM_MUSIC);

   2、开启线程和Handler来准备为每首歌的图片获取做准备

mAlbumArtWorker = new Worker("album art worker");

mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());

   3、利用广播对信息变化、队列状态、播放状态的监听,对抽屉的展开,更新最新播放的状态

registerReceiver(mTrackListListener, metaChangeFilter);

   4、开启线程通过数据库获取到MediaStore.Audio的Album和Arist歌曲信息

new MusicUtils.BitmapDownloadThread(this, null, 0, 20).start();

onStart:

   1、创建连接服务

mToken = MusicUtils.bindToService(this, this);

   2、通过广播信息变化、队列状态、播放状态的监听对播放按钮等的状态进行改变

registerReceiver(mStatusListener, f);

   3、通过广播屏幕的亮灭

 亮  通过2的广播注册 ,并更新歌曲信息,刷新

 灭  刷新状态,并注销2的广播,

   4、刷新时间的显示

 refreshNow();

 

11.MediaPlaybackService此类继承自Service此类提供音乐的播放服务,音乐的播放控制都在内部定义的

12.MusicAlphabetIndexer此类继承自AlphabetIndexer

**13.MusicBrowserActivity应用的入口继承MediaPlaybackActivity实现接口 MusicUtils.Defs

 onCreate

setVolumeControlStream(AudioManager.STREAM_MUSIC);//通过音量侧键控制播放音频音量

init();//控件的初始化,调用的是父类里的init()方法

抽屉控件的初始化(MusicPanelLayout这就是抽屉类,它是自定义控件它的初始化在父类里,其中的控件ListView里在子类里完成,蛟龙音效对应着单独的一个Activity,这个Activity还不是本应用里的一个界面action“android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL”)

然后就是对toolbar的初始化:对搜索图标的跳转意图,以及Navigation图标的对抽屉的监听(打开、关闭)

showScreen然后再显示对应的fragment(它都会对当前打开的哪一个fragment进行保存、获取通过SharePreference)

创建喜欢列表(开启线程,操作数据库)

  利用SimplePanelSlideListener回调MusicPanelLayout,对抽屉的关闭、打开做了在这里的处理。

这里用到了aidl实现跨进程服务。而进程之间实现通信就是通过aidl文件(当然进程本身更是可以使用),主要包括三个步骤,首先,使用aidl语言服务接口,然后根据aidl定义的接口,在具体的service类中实现接口中定义的方法和属性。最后在需要调用的进程中通过相同的aidl文件实现跨进程服务。

在咱们Music中就分为;IMediaPlaybackService ---> (MediaPlaybackService)ServiceStub --->MediaPlaybackService --->MusicBrowerActivity(MusicUtils.bindToService(this, autoshuffle))

Autoshuffle是一个实现ServiceConnection接口的类,在这类里面要是实现两个方法,onServiceConnected是在执行bindService方法的时候自动调用的,主要是用来获取服务对象的。还有一个onServiceDisconnected是在结束绑定服务 unbindService方法的时候自动调用的。

14.MusicPicker此类继承自ListActivity

15.MusicUtils该类提供获取音乐播放状态的辅助方法

16.PlaylistBrowserActivity此类继承自View.OnCreateContextMenuListener,  MusicUtils.Defs此类用于显示播放列表

17.QueryBrowserActivity此类继承自ListActivity实现接口MusicUtils.Defs, ServiceConnection 查询音乐界面

18.RenamePlaylist此类继承自Activity该类用于对音乐列表进行重命名

19.RepeatingImageButton此类继承自ImageButton该类实现长按某个图片时 歌曲的快进

20.ScanningProgress此类继承自Activity显示当前扫描的进度

21.SharedPreferencesCompat存储上次使用时的某些播放器首选项的信息保存

22.SortCursor此类继承自AbstractCursor

23.TouchInterceptor此类继承自ListView

24.TrackBrowserActivity此类继承自ListActivity 实现接口 View.OnCreateContextMenuListener,   MusicUtils.Defs,   ServiceConnection

25.VerticalTextSpinner此类继承自View

26.VideoBrowserActivity此类继承ListActivity 实现接口 MusicUtils.Defs

27.WeekSelector此类继承自Activity

28.还有个定义的 aidl文件IMediaPlaybackService此文件中定义了IPC的接口

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rom_Fisher

赠人玫瑰,手留余香。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值