android 系统音乐播放器分析

原创 2012年03月28日 21:44:08

来不急,就贴到帖子上,明天回公司看

Android SDK 提供了两种类型的 Service ,用于类似 *nix 守护进程或者 windows 的服务

1. 本地服务 Local Service :用于应用程序内部

2. 远程服务 Remote Service :用于 android 系统内部的应用程序之间

前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程式比如 Activity 所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序服用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

不需要和 Activitye 交互的本地服务

本地服务编写比较简单。首先,要创建一个 Service 类,该类继承 android 的 Service 类。然后在 Activity 中的 onCreate 和 onDestory 中分别执行以下语句开启服务和停止服务。

this .startService( new Intent( this , ServiceImpl. class ));

this .stopService( new Intent( this , ServiceImpl. class ));

需要和 Activity 交互的远程服务

上面的示例是通过 startService 和 stopService 启动关闭服务的。适用于服务和 activity 之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用 bind 和 unbind 方法。

具体做法是,服务类需要增加接口,比如 ServiceInterface ,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承 Binder 类并实现 ServiceInterface 接口。还有,就是要实现 Service 的 onBind 方法,不能只传回一个 null 了。

在 android 的 musicplayer 源码中 MediaPlaybackService 使用了以上的服务方式,针对该源码进行分析:

首先需要了解进程间通信、需要 AIDL (以及 Binder )

关于 AIDL 的介绍在文档: docs/guide/developing/tools/aidl.html

关于 IBinder 的介绍在文档: docs/reference/android/os/IBinder.html

以及 Binder : docs/reference/android/os/Binder.html

manifest 中 Service 的语法,见 docs/guide/topics/manifest /service-element.html

以上转自 http://blog.csdn.net/saintswordsman/archive/2010/01/05/5130947.aspx

步骤一:建立 aidl 文件

通过 aidl.exe 会在 gen 中生成该 service 类,该类中的成员变量 stub 实现了以下功能:

extends Binder implements ServiceInterface,源码如下

Java代码  1.interface IMediaPlaybackService  
2.{  
3.    void openfile(String path);  
4.    void openfileAsync(String path);  
5.    void open(in int [] list, int position);  
6.    ...................//接口方法  
7.} 
interface IMediaPlaybackService
{
    void openfile(String path);
    void openfileAsync(String path);
    void open(in int [] list, int position);
    ...................//接口方法

Java代码  1.public interface IMediaPlaybackService extends android.os.IInterface {  
2.    /**生成binder类 */ 
3.    public static abstract class Stub extends android.os.Binder implements 
4.            com.android.mymusic.IMediaPlaybackService {  
5.        private static final java.lang.String DESCRIPTOR = "com.android.mymusic.IMediaPlaybackService";  
6. 
7.        /** Construct the stub at attach it to the interface. */ 
8.        public Stub() {  
9.            this.attachInterface(this, DESCRIPTOR);  
10.        }  
11.        ...................  
12.        ...................  
13.        ...................//binder 方法  
14.    }  
15.          
16.    public void openfile(java.lang.String path)  
17.            throws android.os.RemoteException;  
18.        ...................  
19.    ...................//接口方法  
20.    ...................  
21. 
22.} 
public interface IMediaPlaybackService extends android.os.IInterface {
 /**生成binder类 */
 public static abstract class Stub extends android.os.Binder implements
   com.android.mymusic.IMediaPlaybackService {
  private static final java.lang.String DESCRIPTOR = "com.android.mymusic.IMediaPlaybackService";

  /** Construct the stub at attach it to the interface. */
  public Stub() {
   this.attachInterface(this, DESCRIPTOR);
  }
  ...................
  ...................
  ...................//binder 方法
 }
  
 public void openfile(java.lang.String path)
   throws android.os.RemoteException;
  ...................
    ...................//接口方法
    ...................

}

 

步骤二:编写服务的实现类 MediaPlaybackService

Java代码  1.public class MediaPlaybackService extends Service {  
2. 
3.     ......  
4.   
5.     @Override 
6.    public IBinder onBind(Intent intent) {  
7.        mDelayedStopHandler.removeCallbacksAndMessages(null);  
8.        mServiceInUse = true;  
9.        return mBinder;  
10.    }  
11.    private final IMediaPlaybackService.Stub mBinder = new IMediaPlaybackService.Stub()  
12.    {  
13.          ...................//实现接口方法  
14.    };  
15.} 
public class MediaPlaybackService extends Service {

     ......
 
     @Override
    public IBinder onBind(Intent intent) {
        mDelayedStopHandler.removeCallbacksAndMessages(null);
        mServiceInUse = true;
        return mBinder;
    }
    private final IMediaPlaybackService.Stub mBinder = new IMediaPlaybackService.Stub()
    {
          ...................//实现接口方法
    };
}

 

 

步骤三:编写一个消费这个服务的 Activity : MediaPlaybackActivity: (除此之外还有其他类)

Java代码
1.public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs,  
2.    View.OnTouchListener, View.OnLongClickListener  
3.{  
4.    private IMediaPlaybackService mService = null;  
5. 
6.    @Override 
7.    public void onStart() {  
8.        super.onStart();  
9.        ...................//其他代码  
10. 
11.        if (false == MusicUtils.bindToService(this, serviecConnection)) {  
12.            // something went wrong  
13.        ...................//其他代码  
14.        }  
15. 
16.    private ServiceConnection serviecConnection = new ServiceConnection() {  
17.            public void onServiceConnected(ComponentName classname, IBinder obj) {  
18.                mService = IMediaPlaybackService.Stub.asInterface(obj);  
19.                if (MusicUtils.sService == null) {  
20.                    MusicUtils.sService = mService;  
21.                      
22.                        ...................//其他代码  
23. 
24.                }  
25.            }  
26.            public void onServiceDisconnected(ComponentName classname) {  
27.            }  
28.    };  
29.}  
30.//MusicUtils类:定义了播放器所需要的操作以及service和Activity之间的相互作用的操作  
31.public class MusicUtils {  
32. 
33.    ...................//其他代码  
34.      
35.    public static boolean bindToService(Context context, ServiceConnection callback) {  
36.        context.startService(new Intent(context, MediaPlaybackService.class));  
37.        ServiceBinder sb = new ServiceBinder(callback);  
38.        sConnectionMap.put(context, sb);  
39.        return context.bindService((new Intent()).setClass(context,  
40.                MediaPlaybackService.class), sb, 0);  
41.    }  
42.      
43.    ...................//其他代码  
44.      
45.} 
public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs,
    View.OnTouchListener, View.OnLongClickListener
{
    private IMediaPlaybackService mService = null;

    @Override
    public void onStart() {
        super.onStart();
        ...................//其他代码

        if (false == MusicUtils.bindToService(this, serviecConnection)) {
            // something went wrong
        ...................//其他代码
        }

    private ServiceConnection serviecConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName classname, IBinder obj) {
                mService = IMediaPlaybackService.Stub.asInterface(obj);
                if (MusicUtils.sService == null) {
                    MusicUtils.sService = mService;
                   
                        ...................//其他代码

                }
            }
            public void onServiceDisconnected(ComponentName classname) {
            }
    };
}
//MusicUtils类:定义了播放器所需要的操作以及service和Activity之间的相互作用的操作
public class MusicUtils {

    ...................//其他代码
   
    public static boolean bindToService(Context context, ServiceConnection callback) {
        context.startService(new Intent(context, MediaPlaybackService.class));
        ServiceBinder sb = new ServiceBinder(callback);
        sConnectionMap.put(context, sb);
        return context.bindService((new Intent()).setClass(context,
                MediaPlaybackService.class), sb, 0);
    }
   
    ...................//其他代码
   

 

需要注意:

远程服务往往不只是传递 java 基本数据类型。这时需要注意 android 的一些限制和规定:

   以下转自 http://yangguangfu.javaeye.com/blog/699306

1. android 支持 String 和 CharSequence

2. 如果需要在 aidl 中使用其他 aidl 接口类型,需要 import ,即使是在相同包结构下;

3. android 允许传递实现 Parcelable 接口的类,需要 import ;

4.  android 支持集合接口类型 List 和 Map ,但是有一些限制,元素必须是基本型或者上述三种情况,不需要 import 集合接口类,但是需要对元素涉及到的类型 import ;

非基本数据类型,也不是 String 和 CharSequence 类型的,需要有方向指示,包括 in 、 out 和 inout , in 表示由客户端设置, out 表示由服务端设置, inout 是两者均可设置。


转自:http://blog.csdn.net/bigapple88/archive/2011/03/29/6285411.aspx

下面介绍一下Andriod多媒体框架对开发者提供的支持有哪些。

1. MediaScannerReceiver

这个广播接收者在接收到ACTION_BOOT_COMPLETED、ACTION_MEDIA_MOUNTED或 ACTION_MEDIA_SCANNER_SCAN_FILE 广播时对SD卡中的图片、音乐和视频文件进行了扫描,因为扫描不能影响用户使用,这里启动了一个服务MediaScannerService,扫描的文件类型如下:

/* Audio */
addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg");
addFileType("M4A", FILE_TYPE_M4A, "audio/mp4");
addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");
addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
addFileType("MID", FILE_TYPE_MID, "audio/midi");
addFileType("XMF", FILE_TYPE_MID, "audio/midi");
addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");

/* Video */
addFileType("MP4", FILE_TYPE_MP4, "video/mp4");
addFileType("M4V", FILE_TYPE_M4V, "video/mp4");
addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp");
addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");

/* Image */
addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
addFileType("GIF", FILE_TYPE_GIF, "image/gif");
addFileType("PNG", FILE_TYPE_PNG, "image/png");
addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp");
addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");

/* Audio Play List */
addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl");
addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls");
addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl");

扫描结束后写入到数据库中。

其他的应用程序通过接收MediaScannerService发出的ACTION_MEDIA_SCANNER_STARTED 和ACTION_MEDIA_SCANNER_FINISHED意图能够知道什么时候扫描操作开始和结束。

2. MediaProvider

对于存入数据库的多媒体信息,MediaProvider提供了数据访问的接口。MediaProvider继承了ContentProvider,我们先来看一下数据查询接口:

Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);

Uri:指明要查询的数据库名称加上表的名称,从MediaStore中我们可以找到相应信息的参数,具体请参考开发文档。
Projection: 指定查询数据库表中的哪几列,返回的游标中将包括相应的信息。Null则返回所有信息。
selection: 指定查询条件
selectionArgs:参数selection里有 ?这个符号是,这里可以以实际值代替这个问号。如果selection这个没有?的话,那么这个String数组可以为null。
SortOrder:指定查询结果的排列顺序


下面的命令将返回所有在外部存储卡上的音乐文件的信息:
Cursor cursor = query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null,
null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);



获取ID标签中的歌曲的专辑名:MediaStore.Audio.Media.ALBUM
String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
其他具体参数请参考MediaStore类。

【android】音乐播放器之设计思路

学习Android有一个多月,看完了《第一行代码》以及mars老师的第一期视频通过音乐播放器小项目加深对知识点的理解。从本文开始,将详细的介绍简单仿多米音乐播放器的实现,以及网络解析数据获取百度音乐最...
  • zjngogo
  • zjngogo
  • 2015年10月30日 16:02
  • 6263

android-简单音乐播放器的总结

业务:android的程序,实现播放音乐的功能。 知识点: 1.使用了android的四大组件中的三个(Activity,Service,Broadcast) activity与serivice...
  • tzguo1314
  • tzguo1314
  • 2013年06月08日 00:48
  • 2275

android快捷简单的实现音乐播放器

简单快速的实现自己的音乐播放器,功能相对完善,使用简单
  • hhhccckkk
  • hhhccckkk
  • 2013年08月22日 13:23
  • 5376

Android 音乐播放器的开发教程(十)通知栏Notification的使用 ----- 小达

通知栏Notification的使用         在这一片博客中,小达将自己学习Notification的一些想法和大家分享一哈,学的不是很深,所有有些东西可能解释的不是特别到位,还请各位谅解哈....
  • Jing_Unique_Da
  • Jing_Unique_Da
  • 2015年01月03日 10:21
  • 5240

收集了很多音乐播放器类的Android项目源码,非常不错的开源项目

JieCaoVideoPlayer立志成为Android平台使用最广泛的视频播放控件 http://neast.cn/forum.php?mod=viewthread&tid=61610&fromu...
  • java173842219
  • java173842219
  • 2017年01月05日 19:02
  • 6071

android-音乐播放器实现及源码下载(一)

从本文开始,详细讲述一个音乐播放器的实现,以及从网络解析数据获取最新推荐歌曲以及歌曲下载的功能。 功能介绍如下: 1、获取本地歌曲列表,实现歌曲播放功能。 2、利用硬件加速感应器,摇动手机实现切...
  • u010156024
  • u010156024
  • 2015年08月16日 11:45
  • 29013

Android之音乐播放器——简单版

当我的Android模拟器响起Robert Miles Children的歌曲时,我直接趴下去睡着了。虽然实现播放,但是醒来时发现还是一堆bug,噼里啪啦,搞定初步。        有老师开了两天...
  • iaiti
  • iaiti
  • 2013年10月23日 01:16
  • 7775

Android之简单本地音乐播放器

平台:Android studio APK:http://fir.im/apps/56ea5187e75e2d69af000042 本地的音乐播放器,主要功能就是可以播放音乐,能够读取本地的音乐,并显...
  • I_do_can
  • I_do_can
  • 2016年03月17日 16:52
  • 19971

Android 音乐播放器的实现(三)Service的实现

Service 是运行于幕后的,它并不轻易见人,而正巧,音乐也是只闻其声不见其人的,相信这就是它们在一起的原因。 大家都知道,从Activity中跟Service交互有两种方式: 1)startSer...
  • foolsheep
  • foolsheep
  • 2014年01月20日 20:08
  • 4512

Android简易的音乐播放器实现

1.在sdcard中获取音频文件,实现音乐播放。并且音乐播放要放在服务当中避免受到Activity生命周期影响。2.使用SeekBar进行拖动时要暂停音乐的播放,避免拖动时进度条的更新。3.在使用Me...
  • ProgramMonkey_z
  • ProgramMonkey_z
  • 2017年01月17日 16:48
  • 1684
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android 系统音乐播放器分析
举报原因:
原因补充:

(最多只允许输入30个字)