前言
我们都知道,在Activity中要启动Service有两种方式,一种是startService(),还有另一种是bindService(),两者的使用场景不一样,启动的参数也不同,下面我们要说的是bindService绑定服务:
bindService 绑定服务
bindService可以实现在同个应用程序(or 组件)之间调用,这是在同一个进程中,也可以在不同应用程序之间调用,即跨进程通信
bindService 绑定服务详细过程
1. 自定义一个Service(BindService),在这个Service内创建一个内部类(MyBinder)并继承Binder实现自己的IBinder接口对象,在这个内部类(MyBinder)中定义一个方法返回当前Service实例,即返回BindService实例;
// 2. 实例化一个MyBinder对象mybinder,而mybinder这个对象实现了客户端(调用者)与服务端(Service)的通信
public class BinderService extends Service {
public BinderService() {
}
private MyBinder mybinder = new MyBinder();
// 1. 自定义一个内部类MyBinder类继承Binder, 从而实现IBinder接口
class MyBinder extends Binder{
public BinderService getService() {
return BinderService.this; //返回当前Service类
}
}
}
2. 通过onBind( )方法返回自己的IBinder对象;
// 必须实现的方法,绑定该Service时会回调onBind()方法
@Override
public IBinder onBind(Intent intent) {
Log.i("BindService", "onBind方法被调用!服务绑定成功!");
return mybinder;
}
3.在绑定该Service的类中实例化ServiceConnection接口的实现类,重写onServiceConnected()和onServiceDisconnected()方法,然后直接读取IBinder传递过来的参数;
因为系统会调用onServiceConnected(),从而读取传递服务的 onBind() 方法所返回的 IBinder对象。
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("MainActivity","执行了onServiceConnected(),当前Acitivity与服务连接成功");
mybinder = (BinderService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity","执行了onServiceDisconnected(),当前Acitivity与服务断开连接");
}
};
4. 在绑定该Service的类中的onCreate()方法里,创建Intent对象 并通过bindService()并绑定服务;
// 4. 创建Intent对象 并通过bindService()并绑定服务
Intent bindIntent = new Intent(this,BinderService.class);
bindService(bindIntent,conn,BIND_AUTO_CREATE);
5. 解绑服务
// 调用onUnbind和onDestroyed方法,解绑服务
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
整个过程:
使用BindService绑定Service的过程中:
- 程序依次先调用onCreate(),onBind()方法,可以在onBind()方法中返回自定义的IBinder对象;
- 再接着调用的是 ServiceConnection的onServiceConnected()方法该方法中可以获得 IBinder对象,从而进行相关通信;
- 当Service解除绑定后会自动调用 onUnbind和onDestroyed方法,当绑定多客户端情况下需要解除所有的绑定才会调用onDestoryed方法进行销毁。
完整code
MainActivity.java
package com.example.service;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_bindService;
private Button btn_unbindService;
private BinderService.MyBinder mybinder;
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("MainActivity","执行了onServiceConnected(),当前Acitivity与服务连接成功");
mybinder = (BinderService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity","执行了onServiceDisconnected(),当前Acitivity与服务断开连接");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_bindService = (Button)findViewById(R.id.btn_bindService);
btn_unbindService = (Button)findViewById(R.id.btn_unbindService);
btn_bindService.setOnClickListener(this);
btn_unbindService.setOnClickListener(this);
}
public void onClick(View v){
switch (v.getId()){
case R.id.btn_bindService:
// 4. 创建Intent对象 并通过bindService()并绑定服务
Intent bindIntent = new Intent(this,BinderService.class);
bindService(bindIntent,conn,BIND_AUTO_CREATE);
break;
case R.id.btn_unbindService:
unbindService(conn);
break;
default:
break;
}
}
// 在onDestroy()方法里,解绑服务
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
BinderService.java
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.List;
public class BinderService extends Service {
//1. 自定义一个内部类MyBinder类继承Binder,,从而实现IBinder接口
class MyBinder extends Binder{
public BinderService getService() {
return BinderService.this; //返回当前Service类
}
}
//2. 实例化 一个MyBinder 对象
private MyBinder mybinder = new MyBinder();
public BinderService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i("MyService","执行了onBind(),服务绑定成功");
return mybinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("MyService","执行了onUnbind(),服务解绑成功");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
Log.i("MyService","执行了onCreste(),服务创建成功");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService","执行了onStartCommand(),服务启动成功");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i("MyService","执行了onDestroy(),服务被销");
super.onDestroy();
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务绑定"
android:id="@+id/btn_bindService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务解绑"
android:id="@+id/btn_unbindService"/>
</LinearLayout>
</LinearLayout>
bindService启动方式调用执行的顺序是:
onCreate,接着在调用onBind方法,而onStartCommand这方法在bindService启动这个方式中并不调用;
在Service中执行顺序:
- 在Service内部用内部类得到mybinder对象
- 在onBind方法中返回IBinder实例,返回实例可以是Service实例本身 或者 通过mybinder获取Service公共的方法。如上面第一,二步的方法,这样客户端可以通过该方法得到相应的Service实例,接着调用者客户端执行的流程,客户端执行流程步骤如下:
调用者(客户端)执行的流程
- 先创建ServiceConnetion实例,并重写其方法
- 当执行了onServiceConnected回调时,我们可以通过IBinder实例得到Service实例对象 或 直接调用binder公共方法,这样就实现了client(客户端)和service(服务端)的连接。
注意:
client和Service解除绑定时,onServiceDisconnected并不会被调用;onServiceDisconnected被调用的情况是发生在client和Service连接意外丢失时,这时client和Service一定是断开连接了。