Service作为android四大组建之一,与activity一样是继承于Context. 他们都可以调用Context里定义的getResources()、getContentResolver()等方法。
一、Service生命周期:
// 该方法是Service子类必须要实现该方法
@Overridepublic IBinder onBind(Intent arg0) {
return null;
}
// Service第一次创建后将立即被回调该方法。
@Override
public void onCreate() {
super.onCreate();
}
// 当Service被关闭之前将会回调该方法。
@Override
public void onDestroy() {
super.onDestroy();
}
//当Service每次启动的时候都会回调该方法。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
//当Service上绑定的所有客户端都断开连接时将会回调该方法。
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
当然如同activity一样,在AndroidManifest.xml文件中需要配置Service。通过<intent-filter>来说明该service能被哪些程序启动。
二、启动Service的两种方式。
1:通过Context的StartService()方法 : 通过该方法启动服务,访问者与Service之间没有任何关联,即使访问者退出了,Service仍然运行。
2:通过Context的bindService()方法:通过该方法启动服务,访问者会与Service之间绑定在一起。也就是说Service能够和访问者进行交互。当访问者退出的时候,Service也会终止。
(1)绑定本地Service并通讯
Context中的bindService()方法的完整方法签名为:bindService(Intent service,ServiceConnection conn,int flags)
service:该参数通过intent 来指定要启动的Service
conn:该参数是一个ServiceConnection对象,该对象用于监听访问者的Service之间的连接情况。当访问者与Service之间连接成功时会将回调ServiceConnection对象的onServiceConnected(ComponentName name , IBinder service)方法。当由于异常使得Service与访问者之间断开连接的时候会回调ServiceConnection对象的onServiceDisconnected(ComponentName name)方法(当访问者主动通过unBindService()方法断开Service的时候,不会回调onServiceDisconnection方法)。
flags:指定绑定时是否自动创建Service(如果Service还未创建)。该参数可以指定为0,指不自动创建。或BIND_AUTO_CREATE(自动创建)。 一般情况下StartService()才创建服务,所以说BindService可以再StartService之后BindService()或者 BIND_AUTO_CREATE.
IntentService :
继承IntentService与继承Service的区别在于,继承于Service是在主线程中运行的,如果有耗时操作只能在service中创建新的线程。 而IntentService是创建单独的worl线程来处理所有的Intent请求。在IntentService中onHandlerIntent()方法中会使用单独的worker线程来处理。并且IntentService会使用队列来管理所有请求Intent,当前程序通过Intent来启动服务时,IntentService会将该Intent加入队列中。然后开启一个worker线程(同上的)来依次处理Intent请求。
(2)跨进程Service。
跨进程通讯(interprocess communication ,简称IPC),在android中,为了使个进程之间能够进行数据交换,提供了AIDL Service。
与绑定本地Service不同,本地服务的onBind()方法会把直接IBinder对象本身传递给客户端的ServiceConnection的onServiceConnected方法的第二个参数。但是远程Service的onBind()方法只是将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数,
但是AIDL接口定义语言语法非常简单。它的语法和JAVA接口很相似。但是有以下差异:
1:AIDL定义接口的源代码必须以.aidl结尾
2:AIDL接口中用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导入包,即使它们在同一个包中也需要导包.
AIDL的实现:
1:在工作空间目录下建立一个aidl文件。如下:
保存之后在gen目录下会自动生存一个.java文件(这里是IMyMusicPlayer.java)
2:我们需要在Service中 创建一个IBinder对象 用于实现IMyMusicPlayer.Stub();
在里面实现aidl所需实现的方法 (这里为什么是new IMyMusicPlayerService.Stub())这里内部类呢 因为在gen中自动生成的.java文件中 会自动生成一个内部类Stub
来继承Binder类,与实现IMyMusicPlayerService接口, 因此aidl中的两个方法 play() stop()也是在该类中实现的方法。
该IBinder对象通过onBind 这个方法返回给用户端。 这样服务端就完成了
3:在用户端 首先我们需要得到服务端的aidl文件,注意这里的aidl文件的文件名与路径都是不能变动的。导入该文件之后,我们就可以在自己的进程中绑定该Service并且使用play()方法以及stop()方法了。·
如下所示:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("com.example.aidlService");
bindService(intent, conn, Service.BIND_AUTO_CREATE);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
try {
mService.play();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
IMyMusicPlayerService mService = null;
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
mService = IMyMusicPlayerService.Stub.asInterface(arg1);//服务绑定成功之后获取IBinder对象
}
};
}
当然,我们通过aidl还可以实现更多功能的进程间通讯,而获得更加想要的效果