03.Service总结

136 阅读3分钟

1、Service的基本使用

  1. 创建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)
        }
    }
    
  2. 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>
    
  3. 启动Service,将依次回调onCreate()onStartCommand()方法,如果Service已经创建,则只回调onStartCommand()方法

    private val serviceIntent: Intent by lazy { Intent(this, MyService::class.java) }
    startService(serviceIntent)
    
  4. 停止Service,回调onDestroy()方法

    stopService(serviceIntent)
    

注意:

1、同一个Service,即使多次启动也只会创建一个实例,但会多次调用onStartCommand()方法。startService(Intent)stopService(Intent)的参数可以是同一个Intent实例也可以是不同的。

2、Android8.0以后应用进入后台,service将可能被回收。

2、绑定服务

  1. Service内实现Binder类,在onBind(Intent)返回一个IBinder

    class 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)
            }
        }
    }
    
  2. 目标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)
            }
        }
    
  3. 绑定Service

    private val connection by lazy { MConnection() }
    //设置Context.BIND_AUTO_CREATE标识位,当Service未创建,绑定Service会自动创建该服务
    //还有其他的FLAGS,详情查阅文档
    bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)
    
  4. 解绑Service

    //该ServiceConnection实例必须和绑定服务时是同一个实例。
    unbindService(connection)
    

注意:

1、绑定服务不回调onStartCommand()方法,只回调ServiceConnection.onServiceConnected()方法。同一个对象多次绑定该服务,也只回调一次。

2、多个Activity和Service绑定,获得的Binder实例是同一个。

3、当同时启动Service和绑定Service,需要同时调用stopService()unbindService(),Service才回被销毁。

3、前台服务

从Android8.0开始,只有当服务在前台可见的情况下,Service才能保证稳定运行。前台服务可以保持一直运行。

  1. 创建前台服务,在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)
        }
    
  2. Android9.0以上需要请求前台服务权限

        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
  3. 启动前台服务

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(Intent(this,ForegroundService::class.java))
    } 
    

4、IntentService

IntentService启动后在onHandleIntent()中执行耗时操作,onHandleIntent()中的代码执行完毕后自动回调onDestory()结束服务。

  1. 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)
        }
    }
    
  2. 启动IntentService:

    "$TAG start intent service current thread:${Thread.currentThread().name}".logd(TAG)
    startService(Intent(this, MyIntentService::class.java))
    
  3. 启动IntentService执行结果:

25632d48758bf1c2fe1064055f06844cd79b7aa4.png