本节前言
Android四大组件之一服务(Service)的简单学习
Service的区别及分类
前台服务和后台服务最大的区别是:
1.前台Service在下拉通知栏有显示通知,但后台Service没有。
2.前台Service优先级较高,不会由于系统内存不足而被回收;后台Service优先级较低,当系统
出现内存不足情况时,很有可能会被回收。
有人可能会问,后台服务我们可以自己创建 ONGOING 的 Notification 这样就成为前台服务吗?答案是否定的,前台服务是在做了上述工作之后需要调用 startForeground ( android 2.0 及其以后版本 )或 setForeground (android 2.0 以前的版本)使服务成为 前台服务。这样做的好处在于,当服务被外部强制终止掉的时候,ONGOING 的 Notification 任然会移除掉。
Service生命周期
第一种方式:通过StartService启动Service
通过startService启动后,service会一直无限期运行下去,只有外部调用了stopService()或stopSelf()方法时,该Service才会停止运行并销毁。
要创建一个这样的Service,你需要让该类继承Service类,然后重写以下方法:
onCreate()
1.如果service没被创建过,调用startService()后会执行onCreate()回调;
2.如果service已处于运行中,调用startService()不会执行onCreate()方法。
也就是说,onCreate()只会在第一次创建service时候调用,多次执行startService()不会重复调用onCreate(),此方法适合完成一些初始化工作。
onStartCommand()
如果多次执行了Context的startService()方法,那么Service的onStartCommand()方法也会相应的多次调用。onStartCommand()方法很重要,我们在该方法中根据传入的Intent参数进行实际的操作,比如会在此处创建一个线程用于下载数据或播放音乐等。
onBind()
Service中的onBind()方法是抽象方法,Service类本身就是抽象类,所以onBind()方法是必须重写的,即使我们用不到。
onDestory()
在销毁的时候会执行Service该方法。
这几个方法都是回调方法,且在主线程中执行,由android操作系统在合适的时机调用。
第二种方式:通过bindService启动Service
bindService启动服务特点:
1.bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
2.client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
3.bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁。
Android8.0后启动Service服务
Android在8.0开始限制后台服务,启动后台服务需要设置通知栏,使服务变成前台服务。同时在Android 9.0开始注册权限android.permission.FOREGROUND_SERVICE,并授权权限。
从8.0开始启动服务需要进行判断出来如下:
/**
* Android 8.0及以后,启动服务的形式已经变了
*/
private void startService(Context context) {
Intent intent = new Intent(context, MyForegroundService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
}
同时在Service的onCreate()方法里设置通知栏如下:
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
//创建NotificationChannel
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel(NOTIFICATION_ID,
NOTIFICATION_NAME, NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
//Android9.0会报Caused by: java.lang.SecurityException: Permission Denial:
//android.permission.FOREGROUND_SERVICE---AndroidManifest.xml中需要申请此权限
startForeground(1,getNotification());
}
//这个必须加,不能设置为null
private Notification getNotification() {
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("测试服务")
.setContentText("我正在运行");//标题和内容可以不加
//设置Notification的ChannelID,否则不能正常显示
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_ID);
}
Notification notification = builder.build();
return notification;
}
}
说明:
测试发现Android8.0后如果用startService启动服务,应用退到后台后此服务一会儿就会被杀掉;如果用startForegroundService启动服务,并且添加了消息通知后,应用后台挂起则不会被系统杀掉