目录
-
- [一 概述](#一 概述)
- [二 生命周期](#二 生命周期)
-
- [2.1 启动服务startService()](#2.1 启动服务startService())
- [2.2 绑定服务bindService()](#2.2 绑定服务bindService())
- [2.3 先启动后绑定](#2.3 先启动后绑定)
- [2.4 先绑定后启动](#2.4 先绑定后启动)
- [三 使用](#三 使用)
-
- [3.1 本地服务(启动式)](#3.1 本地服务(启动式))
- [3.2 可通信的服务(绑定式)](#3.2 可通信的服务(绑定式))
- [3.3 前台服务](#3.3 前台服务)
- [3.4 IntentService](#3.4 IntentService)
- 总结
- 参考
一 概述
Service组件一般用来执行长期在后台的任务,如播放音乐、直播、下载文件等。
二 生命周期
官方图,一图解千言
两种使用Service的方法,执行不同的生命周期。
2.1 启动服务startService()
调用startService方法启动,多次启动onCreate只一次,onStartCommand会多次;
需要手动停止,调用stopService方法或stopItSelf。
2.2 绑定服务bindService()
调用bindService方法绑定,一次unBindService就能结束服务;如果多次调用unBindService,会出错。
当绑定的对象销毁时,自动解绑;绑定的对象也可以调用unBindService来进行主动解绑。
2.3 先启动后绑定
onCreate -> onStartCommand -> onBind -> onUnBind -> onDestroy
2.4 先绑定后启动
onCreate -> onBind -> onStartCommand -> onUnBind -> onDestroy
三 使用
都是Compose写的,很简陋,ui部分就不贴出来了。
3.1 本地服务(启动式)
两个按钮,一个启动服务,一个停止服务。
思路:
1.继承Service重写方法
2.注册Service
3.使用启动和停止方法
部分代码:
kotlin
class MyService: Service() {
private val mBinder = MyBinder()
override fun onCreate() {
println("MyService onCreate")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
println("MyService onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(p0: Intent?): IBinder? {
println("MyService onBind")
return mBinder
}
override fun onUnbind(intent: Intent?): Boolean {
println("MyService onUnbind")
return super.onUnbind(intent)
}
override fun onDestroy() {
println("MyService onDestroy")
super.onDestroy()
}
class MyBinder: Binder() {
fun getServiceMethod() {
println("this is service method")
}
}
}
xml
<service android:name=".MyService">
</service>
多次点击启动,再多次点击停止后结果如下,没有问题。
3.2 可通信的服务(绑定式)
思路:
1.同样先继承一个服务,但是多了一个自定义内部类继承binder如MyBinder,并自定义需要的方法,在onBind方法返回的时候return MyBinder的实例
2.注册Service
3.初始化ServiceConnection 实例,并在方法里将service转成MyBinder类型,然后可以执行类的方法。
4.使用绑定和启动方法
部分代码:
kotlin
val connection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
println("onServiceConnected")
val binder = service as MyService.MyBinder
binder.getServiceMethod()
}
override fun onServiceDisconnected(name: ComponentName?) {
println("onServiceDisconnected")
}
}
context.bindService(intent,connection,BIND_AUTO_CREATE)
context.unbindService(connection)
多次点击,和启动式不同,只会执行onBind一次,解绑只能一次,第二次就报错退出。
3.3 前台服务
不同之处在于通知栏会显示服务;优先级比较高,不会由于系统内存不足而被回收;而后台服务会。
部分代码
kotlin
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0,
notificationIntent,
PendingIntent.FLAG_IMMUTABLE
)
val builder = NotificationCompat.Builder(this, "channel_1")
builder.setContentTitle("我是ServiceDemo的前台服务")
builder.setContentText("今天2024.07.24提前下班")
builder.setSmallIcon(R.mipmap.ic_launcher)
builder.setContentIntent(pendingIntent)
val notification = builder.build()
startForeground(1, notification)
注意:
从Android 8.0(API 级别 26)开始,所有通知都必须通过通知渠道发送。通知渠道允许用户为不同类型的通知设置偏好,比如是否显示通知、是否播放声音、是否振动等。
从Android 13(API级别33)开始,对前台服务的管理变得更加严格,以改善用户体验和系统资源的管理。在Android 14(API级别34)中,这一要求被进一步强调。如果你的应用的targetSdkVersion设置为34或更高,那么在调用Service.startForeground()方法之前,你必须在应用的AndroidManifest.xml文件中的元素上明确指定foregroundServiceType属性。
还要配置权限和通知渠道。
bulider的配置也是缺一不可才会显示具体效果
xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<service android:name=".MyService"
android:foregroundServiceType="specialUse">
</service>
效果:
3.4 IntentService
继承自Service,有一个工作线程来执行耗时任务;异步任务执行是按顺序的。会自动停止,不需要手动。
而传统的Service在主线程,不能执行耗时任务。
被弃用了,懒得学了;需要的时候再看看。
适用场景有离线下载任务等-。
总结
- Service有两种使用模式
- Service可以在后台也可以到前台
- Service在主线程,不能执行耗时操作