目录
一,Service简介
Service 服务,是指执行指定系统功能的程序,例程或进程,以便支持其他程序,并且运行期间用户不可见的一种活动机制,例如:后台播放音乐,后台下载等;
Service和Activity同属于一个级别,不同于子线程,service是运行在主线程中的,因此不能进行耗时操作;
二,Service的两种启动方式
(1)非绑定式启动(startService):
- 服务开启后与启动者没有任何关系,service的生命周期独立于启动者,启动者退出,service仍会运行;
- 启动者无法调用service中的方法;
(2)绑定式启动(bindService)
- 启动者(Activity)会和service绑定在一起,两者的生命周期会同步,当启动者退出时,service会跟着被销毁;
- 启动者可以调用service中的方法;
1,非绑定式启动Service
(1) 创建一个类继承Service类,并重写一系列方法:
java
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("MyService", "onBind: ");
return null;
}
@Override
public void onCreate() {
Log.i("MyService", "onCreate: ");
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();
}
}
(2)在Manifest文件中注册指定Service:
(3)调用**startService(Intent intent)**方法启动Service:
java
private void startMyService() {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
2,绑定式启动Service
(1)前两步与非绑定式启动一致,创建Service子类并注册Service:
java
public class MyBindService extends Service {
private final String TAG = "MyBindService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new MyBinder(this);
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
}
(2)绑定式启动Service需要调用**bindService()**方法,这个方法需要三个参数:
java
private void startBindService() {
Intent intent = new Intent(this, MyBindService.class);
isBound = bindService(intent, connection, BIND_AUTO_CREATE);
}
Intent:表示启动意图,也就是想要启动的Service;
connection:相当于启动者(Activity)和Service之间的连接,通过一系列的回调函数来监听访问者和Service的连接情况;
int flag:绑定时是否自动创建Service,这里选择自动创建BIND_AUTO_CREATE;
除了Intent和flag外,我们还需创建一个connection,这里通过匿名内部类的形式创建,并重写两个回调方法。这里onServiceConnected方法中有一个IBinder类型的service,这个service起到了中间人的作用,通过这个service,启动者(Activity)就可以调用Service中的方法:
java
private ServiceConnection connection = new ServiceConnection() {
//创建连接时回调
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//这里 IBinder类型的service 就是我们要绑定的那个service
//通过这个service,Activity就可以调用MyBindService.MyBinder中的方法
}
//断开连接时回调
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
}
};
那么这个service是从哪来的呢?
在我们创建的Service子类中,我们重写了一个onBind的方法,返回的正好是一个IBinder类型的值,这个返回值也就是会传给上面service的值。
java
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new MyBinder(this);
}
所以我们可以在Service子类中创建一个类继承自Binder(Binder实现了IBinder接口),这样Activity通过connection中的service就可以调用MyBinder类中的方法;
进一步,通过构造方法,我们可以将Service传给MyBinder,这样在MyBinder中就可以调用我们Service中的方法,又因为Activity可以调用MyBinder中的方法,所以我们就实现了Activity调用Service的方法,这也就是为什么绑定式启动Service,启动者(Activity)可以调用Service中的方法;
java
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new MyBinder(this);
}
public void Test(){
//Log.i(TAG, "Test: MyBindService的Test方法被调用");
}
public class MyBinder extends Binder{
private MyBindService myBindService;
public MyBinder(){}
public MyBinder(MyBindService bindService){
this.myBindService = bindService;
}
public void Test(){
//Log.i(TAG, "Test: MyBinder的Test方法被调用");
//这样MyBinder就可以调用MyBindService中的方法
//MyBinder作为一个中间人 Activity调用MyBinder的方法 -> MyBinder再调用Service的方法
myBindService.Test();
}
}
绑定式启动Service的全部流程代码:
Activity:
java
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
private Boolean isBound = false;
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setLinsteners();
}
private void setLinsteners() {
binding.btnStartBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startBindService();
}
});
}
private void startBindService() {
Intent intent = new Intent(this, MyBindService.class);
isBound = bindService(intent, connection, BIND_AUTO_CREATE);
}
private MyBindService.MyBinder myBindService;
private ServiceConnection connection = new ServiceConnection() {
//创建连接时回调
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//这里 IBinder类型的service 就是我们要绑定的那个service
//通过这个service,Activity就可以调用MyBindService.MyBinder中的方法
myBindService = (MyBindService.MyBinder)service;
myBindService.Test();
}
//断开连接时回调
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
//Intent intent = new Intent(MainActivity.this, MyBindService.class);
//stopService(intent);
}
};
}
Service:
java
public class MyBindService extends Service {
private final String TAG = "MyBindService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new MyBinder(this);
}
public void Test(){
//Log.i(TAG, "Test: MyBindService的Test方法被调用");
}
public class MyBinder extends Binder{
private MyBindService myBindService;
public MyBinder(){}
public MyBinder(MyBindService bindService){
this.myBindService = bindService;
}
public void Test(){
//Log.i(TAG, "Test: MyBinder的Test方法被调用");
//这样MyBinder就可以调用MyBindService中的方法
//MyBinder作为一个中间人 Activity调用MyBinder的方法 -> MyBinder再调用Service的方法
myBindService.Test();
}
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
}
三,Service的生命周期
1,非绑定式Service的生命周期
启动阶段:启动者(Activity)调用startService
- onCreate():Service被创建时调用,整个生命周期中只会被调用一次;
- onStartCommand():每次调用startService时,该方法会被调用,该方法接收Intent参数,从而可以执行一些命令;
结束阶段:启动者调用stopService() 方法或Service内部调用**stopSelf()**方法;
- onDestroy():Service销毁时调用,与onCreate一样,整个生命周期中只会被调用一次;
2,绑定式Service的生命周期
启动阶段:启动者(Activity)调用bindService
- onCreate():Service被创建时调用,整个生命周期中只会被调用一次;
- onBind():在首次绑定时会被调用一次,同样整个生命周期中只会被调用一次;
结束阶段:当启动者销毁或unBindService方法时,启动者会和Service解除绑定,当没有任何绑定者时,Service会被销毁;
- onUnbind():解除绑定时调用,可多次调用;
- onDestroy():Service销毁时调用,整个生命周期中只会被调用一次;
四,前台Service
前台Service,即可以与用户进行交互的运行在前台的Service,优先级相比于其他两种运行在后台的Service要高,最常见的应用就是通知栏前台控制音乐播放;
1,前台Service的创建
在正常的Service中调用**startForeground()**方法即可将正常服务提升为前台服务,startForeground()方法需要接收一个通知对象,因为前台Service必须在通知栏中进行通知;
java
public class MyForeGroundService extends Service {
private final String TAG = "MyForeGroundService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
//创建一个通知
NotificationManager notificationManager = (NotificationManager) getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(
"channel_id",
"channel_name",
notificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(
this,
"channel_id"
);
Notification notification = builder.build();
//将服务提升为前台服务
startForeground(1, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
}
2,前台Service的结束
前台Service的结束有两种含义:
(1)结束Service本身:通过启动者调用stopService方法或Service内部调用stopSelf方法正常结束Service,Service结束后,通知也会随之移除;
(2)前台Service降级为后台Service:通过Service内部调用**stopForeground(true)**方法将Service退出后台状态,此时Service不会被销毁,当内存不足时,Service可能会被回收。参数true表示移除通知;
前台Service创建和结束的全部流程代码:
Activity:
java
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
private Boolean isBound = false;
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setLinsteners();
}
private void setLinsteners() {
//创建前台Service
binding.btnStartForeGroundService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyForeGroundService.class);
startService(intent);
}
});
//移除前台Service
binding.btnStopForeGroundService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyForeGroundService.class);
intent.putExtra("key_stop", "stopForeGround");
startService(intent);
}
});
}
}
Service:
java
public class MyForeGroundService extends Service {
private final String TAG = "MyForeGroundService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
//创建一个通知
NotificationManager notificationManager = (NotificationManager) getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(
"channel_id",
"channel_name",
notificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(
this,
"channel_id"
);
Notification notification = builder.build();
//将服务提升为前台服务
startForeground(1, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
String keyStop = intent.getStringExtra("key_stop");
if(TextUtils.equals(keyStop, "stopForeGround")){
stopForeground(true);//true表示移除通知
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
}