一、Service 开启和停止
二、Service 执行耗时工作
三、IPC常用方式
四、AIDL(一)同一应用中使用AIDL及原理
五、AIDL(二)不同应用中使用、自定义数据类型及定向Tag
六、AIDL(三)实现回调
七、AIDL(四)获取服务及绑定和Binder传递流程
Service 开启和停止
先定义一个Service
类,名为StartStopService
,继承自Service
,代码如下:
代码1
com/ieening/blogsservicedemo/services/StartStopService.java
public class StartStopService extends Service {
private final String TAG = StartStopService.class.getName();
public StartStopService() {
Log.d(TAG, "executing StartStopService constructor");
}
@Override
public IBinder onBind(Intent intent) {
// Return the communication channel to the service.
// 必须重写该方法,该方法为抽象方法。绑定开启 Service 时会调用该方法,在开启和停止调用方式中不会调用该方法
Log.d(TAG, "executing StartStopService onBind method");
return null;
}
@Override
public void onCreate() {
// Service初次创建会调用该方法,我们可以做一些初始化操作,与 onDestroy相对
Log.d(TAG, "executing StartStopService onCreate method");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 每次显示启动 Service 都会调用该方法
Log.d(TAG, "executing onStartCommand method");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// 每次销毁 Service 时都会调用该方法,在该方法内,可以添加释放资源的操作,与 onCreate 相对
Log.d(TAG, "executing onDestroy method");
super.onDestroy();
}
}
- 必须重写
onBind
方法,该方法为抽象方法。绑定开启Service
时会调用该方法,在开启和停止调用方式中不会调用该方法; Service
初次创建会调用onCreate
方法,我们可以做一些初始化操作,与onDestroy
相对
1.1 显示开启和关闭
首先构建Intent
,然后调用Context
的startService
和stopService
方法。
代码2
com/ieening/blogsservicedemo/MainActivity.java
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private final String TAG = MainActivity.class.getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
// ! 绑定 Activity 和 Service
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "executing ServiceConnection onServiceConnected");
BindUnbindServiceBinder bindUnbindServiceBinder = (BindUnbindServiceBinder) service;
// 获取 MyService 引用
BindUnbindService bindUnbindService = (BindUnbindService) bindUnbindServiceBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "executing ServiceConnection onServiceDisconnected");
// Service 被销毁时调用(内存不足等,正常解绑不会走这)
}
};
binding.startServiceButton.setOnClickListener(v -> {
Log.d(TAG, "click start service button to start service");
// ! 显示开启 Service
Intent intent = new Intent(getApplicationContext(), StartStopService.class);
startService(intent);
v.setEnabled(false);
binding.restartServiceButton.setEnabled(true);
binding.stopServiceButton.setEnabled(true);
});
binding.restartServiceButton.setOnClickListener(v -> {
Log.d(TAG, "click restart service button to restart service");
// ! 显示重启 Service
Intent intent = new Intent(getApplicationContext(), StartStopService.class);
startService(intent);
});
binding.stopServiceButton.setOnClickListener(v -> {
Log.d(TAG, "click stop service button to stop service");
// ! 显示停止 Service
Intent stopIntent = new Intent(this, StartStopService.class);
stopService(stopIntent);
v.setEnabled(false);
binding.startServiceButton.setEnabled(true);
binding.restartServiceButton.setEnabled(false);
});
binding.bindServiceButton.setOnClickListener(v -> {
Log.d(TAG, "click bind service button to bind service");
Intent bindIntent = new Intent(this, BindUnbindService.class);
bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
binding.bindServiceButton.setEnabled(false);
binding.unbindServiceButton.setEnabled(true);
});
binding.unbindServiceButton.setOnClickListener(v -> {
Log.d(TAG, "click unbind service button to unbind service");
unbindService(serviceConnection);
binding.bindServiceButton.setEnabled(true);
binding.unbindServiceButton.setEnabled(false);
});
}
}
先点击start service button
,再点击restart service button
,最后点击stop service button
,可以得到下面的日志:
2024-01-01 08:44:29.672 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D click start service button to start service
2024-01-01 08:44:29.675 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo D executing StartStopService constructor
2024-01-01 08:44:29.677 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo D executing StartStopService onCreate method
2024-01-01 08:44:29.684 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo D executing onStartCommand method
2024-01-01 08:44:40.759 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D click restart service button to restart service
2024-01-01 08:44:40.768 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo D executing onStartCommand method
2024-01-01 08:44:47.630 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D click stop service button to stop service
2024-01-01 08:44:47.634 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo D executing onDestroy method
1.2 绑定开启
上面显示开启和关闭Service
,可以看出,显示开启Service
后,调用者就和Service
没有关联了。比如调用者是个Activity
,Service
的作用是不断地计数。在显示开启Service
的场景下,会存在如下两个问题:
Activity
无法直接(间接通过广播等方法)拿到Service
计数结果,也就是说没法拿到Service
引用。- 当
Activity
退出的时候,若不是主动停止Service
,那么Service
将不会被关闭。不太恰当的比喻是:“管生不管养”。
定义com/ieening/blogsservicedemo/services/BindUnbindServiceBinder.java
继承自Binder
。
代码3
com/ieening/blogsservicedemo/binders/BindUnbindServiceBinder.java
public class BindUnbindServiceBinder extends Binder {
private final String TAG = BindUnbindServiceBinder.class.getName();
private final Service service;
BindUnbindServiceBinder(Service service) { // ! 持有 Service 引用
Log.d(TAG, "executing BindUnbindServiceBinder constructor");
this.service = service;
}
public Service getService() { // ! 返回 Service 引用
Log.d(TAG, "executing BindUnbindServiceBinder getService");
return service;
}
}
定义BindUnbindService
,继承自Service
,代码如下:
代码4
com/ieening/blogsservicedemo/services/BindUnbindService.java
public class BindUnbindService extends Service {
private final String TAG = BindUnbindService.class.getName();
public BindUnbindService() {
Log.d(TAG, "executing BindUnbindService constructor");
}
@Override
public void onCreate() {
// Service初次创建会调用该方法,我们可以做一些初始化操作,与 onDestroy相对
Log.d(TAG, "executing BindUnbindService onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 每次显示启动 Service 都会调用该方法
Log.d(TAG, "executing BindUnbindService onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// 每次销毁 Service 时都会调用该方法,在该方法内,可以添加释放资源的操作,与 onCreate 相对
Log.d(TAG, "executing BindUnbindService onDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) { // ! 返回 Binder 对象
Log.d(TAG, "executing BindUnbindService onBind");
return new BindUnbindServiceBinder(this);
}
}
在显示开启Service
过程中,我们需要重写public abstract IBinder onBind(Intent intent);
,显示场景下该方法并没有调用,而在绑定开启Service
时,需要返回IBiner
的引用给绑定者使用,重写onBind(Intent intent)
方法,如com/ieening/blogsservicedemo/services/BindUnbindService.java
中onBind
方法。方法返回的是BindUnbindServiceBinder
对象的引用,该对象持有了BindUnbindService
引用。 那,绑定者在哪里接收IBinder
的引用呢? 在Activity
里定义ServiceConnection
匿名内部类,代码见代码1中serviceConnection
定义。
有了ServiceConnection
引用,接着就需要和Serice
建立联系,建立联系的过程即是绑定开启Service
的过程。建立联系调用bindService
,解除绑定调用unbindService
,两个方法都在Context
中。
先点击bind service button
,再点击unbind service button
,得到如下日志:
2024-01-01 08:44:52.982 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D click bind service button to bind service
2024-01-01 08:44:52.990 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo D executing BindUnbindService constructor
2024-01-01 08:44:52.990 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo D executing BindUnbindService onCreate
2024-01-01 08:44:52.991 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo D executing BindUnbindService onBind
2024-01-01 08:44:52.991 11694-11694 com.ieenin...viceBinder com.ieening.blogsservicedemo D executing BindUnbindServiceBinder constructor
2024-01-01 08:44:53.000 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D executing ServiceConnection onServiceConnected
2024-01-01 08:44:53.000 11694-11694 com.ieenin...viceBinder com.ieening.blogsservicedemo D executing BindUnbindServiceBinder getService
2024-01-01 08:45:21.910 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo D click unbind service button to unbind service
2024-01-01 08:45:21.912 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo D executing BindUnbindService onDestroy