一、BindService
在Android开发中,启动Service有两种方式:bindService和startService。本文重点介绍的是bindService,也算是记录一下自己的学习过程,便于回顾。
首先看一下,bindService这个方法:
bindService(Intent service, ServiceConnection conn,int flags)
复制代码
Intent:就是你要绑定的服务,需要明确的声明。
ServiceConnection:一个接口,包含两个回调onServiceConnected和onServiceDisconnected
flags:一般选用BIND_AUTO_CREATE,下面的分析都是基于这个flag
BIND_AUTO_CREATE:当bindService时,该服务如果不存在则自动创建该服务,Service生命周期:onCreate-->onBind;如果服务存在,只会调用onBind;
绑定服务:
Intent intent = new Intent();
intent.setClassName("com.dyj.aidldemocallback", "com.dyj.aidldemocallback.BookManagerService");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
复制代码
绑定服务成功之后,会回调onServiceConnected,当服务端意外挂掉之后,会回调onServiceDisconnected。
当服务端意外挂掉之后,等1s,系统会再次尝试去bind服务端一次:
Scheduling restart of crashed service com.dyj.aidldemocallback/.BookManagerService in 1000ms
复制代码
如果服务端再次挂掉,系统则不会再去尝试bind服务端:
Service crashed 2 times, stopping: ServiceRecord{24f5e9af u0 com.dyj.aidldemocallback/.BookManagerService}
复制代码
如果当服务端挂掉的时候,不想让系统主动再去bind服务端的话,可以在onServiceDisconnected方法中直接调用unbindService。
有以下几点需要注意:
1.只要调用了bindService,不管是否bind成功,当进程退出的时候都应当调用unbindService,释放资源
2.bindService可以多次调用,unbindService只能调用一次(指的是,绑定成功之后,只能调用一次)。
当调用unbindService时,Service生命周期:onUnbind-->onDestroy
二、服务端和客户端通信
当Service绑定成功之后,服务端和客户端就可以进行通信了,可以使用AIDL进行通信,这里写一个简单的demo。
新建一个工程,然后创建两个aidl文件:IManagerInterface 和 ICallbacklInterface
// ICallbacklInterface.aidl
package com.dyj.aidldemocallback;
// Declare any non-default types here with import statements
interface ICallbacklInterface {
void call();
}
复制代码
// IBookManagerInterface.aidl
package com.dyj.aidldemocallback;
import com.dyj.aidldemocallback.ICallbacklInterface;
// Declare any non-default types here with import statements
interface IManagerInterface {
void test();
void setCallBack(ICallbacklInterface callback);
}
复制代码
然后,build一下工程,会在build\generated\source\aidl下面生成两个同名的java文件,待会要用到。
先看一下服务端的实现,当客户端bind服务端时,服务端要返回一个IBinder给客户端,所以,服务端需要创建一个IBinder实例,如下:
private ICallbacklInterface mICallbacklInterface;
private Binder mBinder = new IManagerInterface.Stub() {
@Override
public void test() throws RemoteException {
Log.d(TAG, "[Server] client call server test:" + Thread.currentThread().getName());
mICallbacklInterface.call();
}
@Override
public void setCallBack(ICallbacklInterface callback) throws RemoteException {
mICallbacklInterface = callback;
}
};
复制代码
客户端通过这个Binder,就可以创建IManagerInterface实例了,然后就可以调用服务端的方法了,服务端如果想方便的获取客户端的某些数据,可以通过接口回调的方式,ICallbacklInterface就是客户端提供给服务端的一个接口。服务端到此就完事了,接下来看一下客户端的实现。
首先,将服务端生成的那两个java文件,拷贝到客户端,确保和服务端的路径是一样的(包名相同),然后客户端要创建一个ServiceConnection对象:
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "[Client] onServiceConnected success :" + Thread.currentThread().getName());
mIBookManagerInterface = IManagerInterface.Stub.asInterface(service);
try {
mIBookManagerInterface.setCallBack(mICallbacklInterface);
mIBookManagerInterface.test();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
unbindService(mServiceConnection);
Log.d(TAG, "[Client] onServiceConnected fail :" + Thread.currentThread().getName());
}
};
复制代码
然后调用一下bindService就可以了,运行效果如下:
编写AIDL文件时要注意导包,即使在同一个包中,也要进行导包!
demo源码:github.com/dyjAndroid/…