1、Service的基本使用
-
创建Service
class MyService : Service() { private val TAG = this.javaClass.simpleName override fun onBind(intent: Intent): IBinder? { return null } //服务创建时执行 override fun onCreate() { super.onCreate() "service onCreate".logd(TAG) } //每次启动服务时执行 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { "service start".logd(TAG) return super.onStartCommand(intent, flags, startId) } //服务销毁时执行 override fun onDestroy() { super.onDestroy() "service onDestory".logd(TAG) } } -
Manifest中注册Service。属性enabled缺省值为true,表示该服务可被初始化。如果设置为false,则无法正常启动该Service。属性exported表示该组件能否被外部应用引用,Android12(SDK=31)以后,当存在过滤器时,需要强制设置为true,否则无法安装应用。
<application ...> <service android:name=".service.MyService" android:enabled="true" android:exported="true"></service> </application> -
启动Service,将依次回调
onCreate()、onStartCommand()方法,如果Service已经创建,则只回调onStartCommand()方法private val serviceIntent: Intent by lazy { Intent(this, MyService::class.java) } startService(serviceIntent) -
停止Service,回调
onDestroy()方法stopService(serviceIntent)
注意:
1、同一个Service,即使多次启动也只会创建一个实例,但会多次调用
onStartCommand()方法。startService(Intent)和stopService(Intent)的参数可以是同一个Intent实例也可以是不同的。2、Android8.0以后应用进入后台,service将可能被回收。
2、绑定服务
-
Service内实现Binder类,在
onBind(Intent)返回一个IBinderclass MyService : Service() { private val TAG = this.javaClass.simpleName private val mBinder by lazy { MyBinder() } override fun onBind(intent: Intent): IBinder { return mBinder } inner class MyBinder : Binder() { fun runOnService() { "run on service".logd(TAG) } } } -
目标Activity内创建一个ServiceConnection用于绑定服务
private lateinit var myBinder: MyService.MyBinder inner class MConnection : ServiceConnection { //服务绑定成功时回调 override fun onServiceConnected(name: ComponentName?, service: IBinder?) { "service connected".logd(TAG) myBinder = service as MyService.MyBinder myBinder.runOnService() } //服务创建失败或者被杀掉时回调 override fun onServiceDisconnected(name: ComponentName?) { "service disconnected".logd(TAG) } } -
绑定Service
private val connection by lazy { MConnection() } //设置Context.BIND_AUTO_CREATE标识位,当Service未创建,绑定Service会自动创建该服务 //还有其他的FLAGS,详情查阅文档 bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE) -
解绑Service
//该ServiceConnection实例必须和绑定服务时是同一个实例。 unbindService(connection)
注意:
1、绑定服务不回调
onStartCommand()方法,只回调ServiceConnection.onServiceConnected()方法。同一个对象多次绑定该服务,也只回调一次。2、多个Activity和Service绑定,获得的Binder实例是同一个。
3、当同时启动Service和绑定Service,需要同时调用
stopService()和unbindService(),Service才回被销毁。
3、前台服务
从Android8.0开始,只有当服务在前台可见的情况下,Service才能保证稳定运行。前台服务可以保持一直运行。
-
创建前台服务,在
onCreate()方法中创建一个通知,通过startForeground()将Service转换为前台服务。class ForegroundService : Service() { private val TAG = this.javaClass.simpleName override fun onBind(intent: Intent): IBinder? { return null } override fun onCreate() { super.onCreate() "forground service onCreate".logd(TAG) //Android8.0以上需要创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val channel = NotificationChannel( "my_service", "前台Service通知", NotificationManager.IMPORTANCE_DEFAULT ) manager.createNotificationChannel(channel) } val intent = Intent(this, MainActivity::class.java) val pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE) val notification = NotificationCompat.Builder(this, "my_service") .setContentTitle("This is content title") .setContentText("This is content text") .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pi) .build() startForeground(1, notification) } -
Android9.0以上需要请求前台服务权限
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> -
启动前台服务
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(Intent(this,ForegroundService::class.java)) }
4、IntentService
IntentService启动后在onHandleIntent()中执行耗时操作,onHandleIntent()中的代码执行完毕后自动回调onDestory()结束服务。
-
IntentService的创建:
class MyIntentService : IntentService("MyIntentService") { private val TAG = this.javaClass.simpleName override fun onHandleIntent(intent: Intent?) { "$TAG onHandleIntent current thread:${Thread.currentThread().name}".logd(TAG) } override fun onDestroy() { "$TAG onDestory current thread:${Thread.currentThread().name}".logd(TAG) } } -
启动IntentService:
"$TAG start intent service current thread:${Thread.currentThread().name}".logd(TAG) startService(Intent(this, MyIntentService::class.java)) -
启动IntentService执行结果: