Download presentation
Presentation is loading. Please wait.
1
第17章 音乐之声 --音乐播放器 授课老师:高成珍 QQ号:1281147324 QQ群:287966120、314753495
网络资源:
2
本章案例效果分析
3
本章案例效果分析
4
本章案例效果分析
5
案例概述 本例主要实现音乐播放器的常见功能,包括获取本地音乐、音乐的分 类、音乐播放模式的设置(单曲循环、随机播放、列表循环)、控制音乐 的播放进度、切换音乐(第一首、上一首、播放/暂停、下一首、最后一 首)、将音乐添加到播放列表、播放新音乐时发送通知、将音乐设置为铃 声等功能。 音乐文件往往比较大,直接放在应用中既不实际,灵活性、扩展性也 不好,那么如何获取音乐文件呢?音乐播放是一种比较耗时的操作,通常 将其放在后台执行,而主线程可以继续做其它的事情,例如一边浏览网页 一边听音乐,那么前后台之间是如何进行通信的呢?退出音乐播放界面后 ,又应该如何返回该页面进行设置呢?
6
音乐播放器功能概述 获取本机存储卡中所有的mp3格式的音乐,并以列表的形式显示;
将音乐进行分类,如按艺术家和按专辑分类,并进行简单统计,统计每类中包含的音乐数量,单击某一项后显示该类别下所有的音乐; 实现播放列表功能,用户可以将自己喜欢的歌曲添加到播放列表中,播放时可从播放列表中开始播放音乐; 将某一首音乐设置为手机铃声; 显示当前音乐的播放时间和进度,支持拖动拖动条来改变音乐的播放进度; 能够控制音乐的播放、暂停,实现第一首、上一首、下一首、最后一首功能; 支持多种音乐播放形式,如列表循环、单曲循环、随机播放、结束后停止等。
7
音乐播放器的主要功能流程
8
ContentProvider ContentProvider是不同应用程序之间进行数据交换的标准API,为 存储和读取数据提供了统一的接口;通过ContentProvider,应用程序间 可以实现数据共享;Android内置的许多应用都使用ContentProvider向 外提供数据,供开发者调用(如视频、音频、图片、通讯录 等),本例中就 调用了本机的音频信息。 那么ContentProvider是如何对外提供数据,又是如何实现这一机制 的呢? ContentProvider以某种URI的形式对外提供数据,允许其他应用 访问或修改数据,其他应用程序使用ContentResolver调用方法根据URI 去操作指定的数据。而方法内部实际上是调用该ContentProvider的对 应方法,而ContentProvider方法内部是如何实现的,其他应用程序是不 知道具体细节的。只是知道有那个方法,这就达到了统一接口的目的。
9
ContentProvider共享数据 ContentProvider是Android四大组件之一,如果要开发自己的ContentProvider必须实现Android系统提供的ContentProvider基类,并且需要在AndroidManifest.xml文件中进行配置。 1、继承ContentProvider并重写增、删、查、改等方法; 2、在AndroidManifest.xml使用<provider>对该ContentProvider进行配置。 <manifest .... > <application....> <provider android:name=".MyProvider" android:authorities="iet.jxufe.cn.android.provider.myprovider"/> </application> </manifest> 注意:authorities是必备属性,如果没有authorities属性程序会报错。
10
ContentProvider基类的常用方法
abstract boolean onCreate():该方法在ContentProvider创建后 调用,当其他应用程序第一次访问ContentProvider时,ContentProvider会被创建,并立即调用该方法; abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):根据Uri查询符合条件的全部记录,其中projection是所需要获取的数据列; abstract int update(Uri uri,ContentValues values,String select,String[] selectArgs):根据Uri修改select所匹配的全部记录; abstract int delete(Uri uri,String selection,String[] selectionArgs):根据Uri删除符合条件的全部记录; abstract Uri insert(Uri uri, ContentValues values):根据Uri插入values对应的数据,ContentValues类似于map,存放的是键值对; abstract String getType(Uri uri):该方法返回当前Uri所代表的数据的MIME类型。如果该Uri对应的数据包含多条记录,则MIME类型字符串应该以vnd.android.curor.dir/开头,如果该Uri对应的数据只包含一条记录,则MIME类型字符串应该以vnd.android.cursor.item/开头。
11
调用ContentProvider的步骤
获取应用程序所暴露的数据对应的URI; 调用当前Context对象的getContentResolver()方法获取ContentResolver对象; 调用ContentResolver对象的增删查改方法对暴露的数据进行操作。 本例调用系统中为音视频提供的ContentProvider,从而获取设备中的音视频信息。系统提供的获取手机外部存储卡(SDCard)中音乐信息对应的URI为:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI。
12
Service服务 Service(服务)与Activity类似,都是Android的四大组件之一,并且都是从Context类派生而来,最大区别在于Service没有实际的界面,一直在后台运行,这样可以不影响用户做其它事情。Service主要有两种用途:后台运行和跨进程访问。 Service本身不能直接运行,需借助于Context对象。运行Service主要有两种方式: 调用Context对象的startService() 方法启动。启动者与Service之间没有关联,该Service将一直在后台执行,直到有进程调用stopService(),或者Service自杀(stopSelf())。 调用Context对象的bindService() 方法绑定。Service和绑定它的Context对象同生共死,注意:一个服务可以与多个对象绑定,只有当所有的对象都与之解绑后,该服务才会被销毁。
13
Service服务 以上两种方式也可以混合使用,即一个Service既可以被某个Context对象启动也可以与其它Context对象绑定,此时只有调用stopService(),并且调用unbindservice()方法后,该Service才会被销毁。 注意:虽然服务用于执行一些耗时的操作,但服务仍运行在它所在进程的主线程,并没有创建自己的线程,也没有运行在一个独立的进程上,这意味着,如果你的服务需要做一些消耗CPU或者阻塞的操作,你应该在服务中创建一个新的线程去处理。通过使用独立的线程,可以降低程序出现ANR(Application No Response程序没有响应)的风险,程序的主线程仍然可以保持与用户进行流畅的交互。
14
Service服务 与创建Activity类似,开发Service时需要继承Android系统为我们提供的Service基类,然后根据需要实现一些回调方法。系统中Service类的主要方法如下。 abstract IBinder onBind(Intent intent):该方法是一个抽象方法,因此所有Service的子类必须实现该方法。该方法将返回一个IBinder对象,应用程序可通过该对象与Service组件通信; void onCreate():当Service第一次被创建时,将立即回调该方法; void onDestroy():当Service被关闭之前,将回调该方法; void onStartCommand(Intent intent, int flags,int startId):该方法的早期版本是void onStart(Intent intent, int startId),每次客户端调用startService()方法启动该Service时都会回调该方法; boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。
15
Service服务 自定义的Service子类必须实现onBind()方法,选择性的实现其它方法,本例中的MusicService类还实现了onCreate()方法(在该方法中执行一些初始化的操作)和onDestroy()方法(在该方法中执行一些扫尾工作)。然后还需在AndroidManifest.xml文件中对该Service子类进行配置,配置时可通过<intent-filter.../>元素指定它可被哪些Intent启动。 <service android:name=“.MyService”> <intent-filter> <action android:name=“iet.jxufe.cn.android.MyService”/> </intent-filter> </service> 程序中用于启动Service的Intent中Action的值一定要与这里<action>标签的值一致,程序就是根据Action的值来查找相应的Service从而启动它。
16
Service服务 本例中Service是被显式启动的,而不是按条件启动,所以配置时只需简单指定Service的完整类名。
<service android:name=".MusicService"></service> 本例中,当退出音乐应用后,我们希望仍然能够继续播放音乐,因此,需采用通过startService()方法来启动Service方式。音乐启动后,Service与启动它的Context之间没有任何关系。这样就带来一个问题,当我们需要通过前台来控制音乐的播放时,后台如何知道呢?后台音乐播放完毕继续下一首时,前台如何随之变化呢?也就是说此时我们如何实现前后台间的交互呢?为了解决这个问题,Android为我们提供了一种机制—广播。
17
BroadcastReceiver广播接收器
广播是一种广泛运用在应用程序之间传输信息的机制,而BroadcastReceiver是对发送出来的广播进行过滤接收并响应的一类组件。BroadcastReceiver本质上是一种全局监听器,用于监听系统全局的广播消息,因此它可以非常方便地实现系统中不同组件之间的通信。 BroadcastReceiver用于接收指定Intent的广播,而广播的发送是通过Context对象的sendBroadcast()以及sendOrderedBroadcast()来实现的。通常一个广播Intent可以被订阅了该Intent的多个广播接收者所接收,如同一个广播台,可以被多位听众收听一样。 BroadcastReceiver自身并不实现图形用户界面,但是当它收到某个消息后,可以启动Activity作为响应,或者通过NotificationManager提醒用户,或者启动Service等。
18
BroadcastReceiver广播接收器
创建需要启动的BroadcastReceiver的Intent; 调用Context对象的sendBroadcast()(发送普通广播)或sendOrderedBroadcast()(发送有序广播)方法来启动指定的BroadcastReceiver。 BroadcastReceiver是Android四大组件之一,开发自己的BroadcastReceiver与开发其他组件一样,只需要继承Android系统中提供的BroadcastReceiver基类,然后实现里面的onReceive(Context context, Intent intent) 抽象方法即可。接收到广播后,会立即回调该方法,通过传入的intent对象,可以很方便的获取广播传递的一些数据。
19
BroadcastReceiver注册 静态注册,在清单文件中,通过<receiver>标签实现:
<receiver android:name=".MyBroadcastReceiver"> <intent-filter > <action android:name="iet.jxufe.cn.android.myBroadcastReceiver"> </action> </intent-filter> </receiver> 动态注册,在Java代码中 实现: MyBroadcastReceiver myBroadcastReceiver=new MyBroadcastReceiver(); IntentFilter filter=new IntentFilter(); filter.addAction("iet.jxufe.cn.android.myBroadcastReceiver"); registerReceiver(myBroadcastReceiver, filter);
20
案例中的广播接收关系
21
媒体播放器MediaPlayer Android的多媒体框架支持一些常见的媒体类型如音频、视频、图片等,开发者可以很方便的在应用中集成音频、视频等,这些媒体既可以保存在应用程序的资源文件中,也可以保存在手机的内、外存储器中,还可以是来自于网络的数据流。所有这些都需要使用到媒体播放相关API,其中最简单的就是MediaPlayer。 获取MediaPlayer对象有两种方式: 调用MediaPlayer对象的静态方法create(); 使用new关键字来创建。 二者的区别在于使用new创建的MediaPlayer实例处于空闲Idle状态,使用create()方法创建的MediaPalyer实例处于Prepared()状态。
22
媒体播放器状态间转化
23
媒体播放器常见的事件处理 setOnCompletionListener(MediaPlayer.OnCompletionListener listener):为MediaPlayer的播放完成事件绑定事件监听器; setOnErrorListener(MediaPlayer.OnErrorListener listener):为MediaPlayer的播放错误事件绑定事件监听器; setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当MediaPlayer调用prepared()方法时触发该监听器; setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):当MediaPlayer调用seek()方法时触发该监听器。
24
媒体播放器的开发步骤 1)播放应用的资源文件,即音频文件存放在res/raw文件夹下。
a、调用MediaPlayer的create(Context context,int resId)方法加载指定资源文件; b、调用MediaPlayer的start()、pause()、stop() 等方法控制音频的播放、暂停、停止等。 2) 播放手机内、外存储器上的音频文件,即音频文件存放在手机上,与应用软件无关。 a、创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(String path)方法装载指定的音频文件; b、调用MediaPlayer对象的prepare()方法准备音频; c、调用MediaPlayer的start()、pause()、stop() 等方法控制音频播放。
25
媒体播放器的开发步骤 3)播放应用的原始资源文件,即音频文件存放在assets目录下。
a、调用Context的getAssets() 方法获取应用的AssetManager; b、调用AssetManager对象的openFd(String name)方法打开指定的原生资源,该方法返回一个AssetFileDescriptor对象; c、调用AssetFileDescriptor的getFileDescriptor()、getStartOffset()和getLength()方法来获取音频文件的FileDescriptor、开始位置、长度等; d、创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(FileDescriptor fd,long offset, long length)方法来装载音频资源; e、调用MediaPlayer对象的prepare()方法准备音频; f、调用MediaPlayer的start()、pause()、stop() 等方法控制播放。
26
媒体播放器的开发步骤 4)播放来自网络的音频文件,即音频文件存放在网络上。 a、根据网络上的音频文件所在的位置创建Uri对象;
b、创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(Context context,Uri uri)方法装载Uri对应的音频文件; c、调用MediaPlayer对象的prepare()方法准备音频; d、调用MediaPlayer的start()、pause()、stop()等方法控制音频播放。 案例中使用的是哪一种?
27
Notification通知 Notification是显示在手机状态栏上的通知,状态栏位于手机屏幕的最上方,主要显示手机当前的网络状态、电池状态、时间等。Notification代表的是一种具有全局效果的通知,通过它可以查看该通知的详细信息,Notification通过NotificationManager服务来发送。与对话框类似,Notification的创建也需要借助其内部类Builder。 发送Notification的主要步骤如下 调用getSystemService()方法获取系统的NotificationManager服务; 通过Builder构造器创建一个Notification对象; 为Notification设置各种属性; 通过NotificationManager发送Notification。
28
Notification通知 内部类Builder的主要方法如下 setAutoCancel():设置点击通知后,状态栏是否自动删除通知;
setDefaults():使用系统的默认设置; setContent():设置通知显示的View; setContentIntent():设置点击通知后将要启动的PendingIntent; setContentText():设置通知内容; setContentTitle():设置通知标题; setLargeIcon():设置通知的大图标; setLights():设置通知的灯光; setSound():设置通知的声音; build():返回一个已构建好的Notification;
29
课后思考题 本例中只能将音乐设置为手机铃声,请 在此基础上添加可设置为通知铃声、闹 钟铃声功能。
30
课后思考题 1.定义好ContentProvider后,需要在清单文件中进行配置,配置<provider>标签时,以下哪个属性是必须的。( ) A)android:name B)android:authorities C)android:exported D)A和B 2.下列不属于Service生命周期的回调方法是 ( )。 A)onCreate() B)onBind() C)onStart() D)onStop() 3.开发Service组件时,需开发一个类使其继承系统提供的Service类,该类中必须实现Service中的以下哪个方法( )。 A)onCreate() B)onBind() C)onStartCommand() D)onUnbind()
Similar presentations