android播放器(music player)源码分析1-Service,Binder,ServiceConnection

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 是两者均可设置。

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/bigapple88/article/details/6285411
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞