大家好,又见面了,我是你们的朋友全栈君。
绑定服务是客户端–服务器接口中的服务器。组件(如activity)和服务进行绑定后,可以发送请求、接收响应、执行进程间通信(IPC)。不会无限期在后台运行。
要提供服务绑定,必须实现onBind()回调方法,该方法返回的IBinder对象定义了客户端用来与服务进行交互的编程接口。
客户端可以通过调用bindService()绑定到服务。调用时,必须提供ServiceConnection的实现,后者会监控与服务的连接,当Android系统创建客户端与服务之间的连接时,会对ServiceConnection回调onServiceConnected(),向客户端传递用来与服务通信的IBinder。当实现绑定服务的时候,最重要的环节是定义onBind()回调方法返回的接口。
必须提供IBinder,用以提供客户端与服务进行交互的接口。
@Override public IBinder onBind(Intent arg0) { return sBinder;
}
客户端绑定到服务步骤:
1.实现ServiceConnection,重写两个回调方法:onServiceConnected()—系统会调用该方法以传递服务的onBind()返回的IBinder;onServiceDisconnected()—Android系统会在与服务的连接以外中断(或者随着activity 的生命周期stop)时调用该方法,当客户端取消绑定的时候,不会回调该方法
2.调用bindService(),传递ServiceConnection
3.当系统调用onServiceConnected()的回调方法时,可以使用接口定义的方法开始调用服务
4.要断开与服务的连接,请调用unBindService()
如果应用在客户端与服务仍然绑定的状态下被销毁了,则销毁会导致客户端取消绑定。
扩展binder类:通过扩展Binder类并重onBind()返回它的一个实例创建接口,客户端收到Binder后可以利用它直接访问Binder实现中的,甚至service中可用的公共方法
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
LocalBinder为客户端提供了getService方法,以检索LocalService的当前实例。这样客户端便可调用服务中的公用方法。如客户端可以调用服务中的getRandomNumber()方法。
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
上例说明客户端如何使用ServiceConnection的实现和onServiceConnected()的回调绑定到服务,点击按键,会调用服务中的公共方法getRandomNumber()。客户端应在适当的时机进行取消绑定,如例子中在onStop()的时候进行取消服务绑定。
使用Messenger:如果想让接口跨不同进程工作,可以使用Messenger为服务创建接口。服务可以这种方式定义对应于不同类型Message对象的handler。该Handler是Messenger的基础,后者可以与客户端分享一个IBinder,从而让客户端利用Message对象向服务发送命令。
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
服务就是在Handler的handleMessage()方法中接收传入的message,并根据what成员决定下一步操作。客户端只需要根据服务返回的IBinder创建一个Messenger,然后利用send发送一条消息:
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
使用AIDL:AIDL(Android接口定义语言)执行所有将对象分解成原语的工作,操作系统可以识别这些原语并将它们编组到各进程中以执行IPC。如果想让服务同时处理多个请求,可以直接使用AIDL,这种情况下服务必须具备多线程处理能力,并采用线程安全式设计。如果需要使用AIDL,必须创建一个定义编程接口的.aidl 文件。AndroidSDK工具利用该文件生成一个实现接口并处理IPC的抽象类,随后可在服务内对其进行扩展。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132629.html原文链接:https://javaforall.cn