一个长期后台运行的服务

在一台Android 11的设备上,写了一个服务,发现运行1分钟后服务就被杀了,服务如下:

class MyService : Service() {

    private var run = false

    private fun log(msg: String) = Log.i("MyService", msg)

    override fun onCreate() {
        super.onCreate()
        log("onCreate")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        log("onStartCommand")
        if (!run) {            
            run = true
            thread {
                while (run) {
                	// 每秒打印一下当前时间
                    log("${DateFormat.format("HH:mm:ss", System.currentTimeMillis())}")
                    SystemClock.sleep(1000)
                }
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        run = false
        log("onDestroy")        
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

要解决这个问题比较简单,把目标版本调低即可,例如:targetSdk = 22

如果目标版本比较高,可以使用前台服务,如下:

class MyService : Service() {

    companion object {
        private const val CHANNEL_ID = "MyChannelID"
    }

    private var run = false

    private fun log(msg: String) = Log.i("MyService", msg)

    override fun onCreate() {
        super.onCreate()
        log("onCreate")
        createNotificationChannel()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        log("onStartCommand")
        if (!run) {
            // 创建通知
            val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("守护程序服务")
                .setContentText("服务正在运行...")
                .setSmallIcon(R.drawable.ic_stat_name)
                .setSound(null) // Android 8.0以下时在通知对象中禁止通知声,Android 8.0及以上的通知渠道对象中禁止通知声音
                .build()

            // 启动前台服务
            startForeground(1, notification)

            run = true
            thread {
                while (run) {
                    log("${DateFormat.format("HH:mm:ss", System.currentTimeMillis())}")
                    SystemClock.sleep(1000)
                }
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        run = false
        log("onDestroy")
        // 停止前台服务并移除通知
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            stopForeground(STOP_FOREGROUND_REMOVE)
        } else {
            @Suppress("DEPRECATION")
            stopForeground(true)
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannelCompat
                .Builder(CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_HIGH)
                .setName("守护程序通知频道")
                .setSound(null, null) // Android 8.0及以上的在此处可禁止通知声
                .build()
            val manager = NotificationManagerCompat.from(this)
            manager.createNotificationChannel(channel)
        }
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

在需要的地方启动服务:

startService(Intent(this, MyService::class.java))

不需要时关闭服务:

stopService(Intent(this, MyService::class.java))

还需要声明前台服务的权限:

<!--允许前台服务,在Android9.0的时候出的权限,如果目标版本大于等于9.0,则需要添加该权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

这个权限在Android 9.0的时候才出的,所以,如果目标版本低于9.0版本的话,可以不用声明前台服务权限,而且前台服务在很早的版本就已经有了,但那时不需要权限的。

相关推荐

  1. 一个长期后台运行服务

    2024-05-14 18:18:16       34 阅读
  2. docker 部署并运行一个服务

    2024-05-14 18:18:16       33 阅读
  3. 托管你程序——命令行后台运行记录

    2024-05-14 18:18:16       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-14 18:18:16       91 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-14 18:18:16       97 阅读
  3. 在Django里面运行非项目文件

    2024-05-14 18:18:16       78 阅读
  4. Python语言-面向对象

    2024-05-14 18:18:16       88 阅读

热门阅读

  1. NLP(15)-序列标注任务

    2024-05-14 18:18:16       22 阅读
  2. 单链表与双链表

    2024-05-14 18:18:16       24 阅读
  3. 蓝桥杯单片机组——国赛1 各模块的基础模板

    2024-05-14 18:18:16       29 阅读
  4. 微信小程序-禁止页面下拉回弹

    2024-05-14 18:18:16       31 阅读
  5. Frida逆向与利用自动化

    2024-05-14 18:18:16       33 阅读
  6. NIUKE SQL:大厂面试真题(四) 【某滴打车】

    2024-05-14 18:18:16       30 阅读
  7. 回溯算法(Backtracking Algorithm)

    2024-05-14 18:18:16       28 阅读
  8. react生命周期及用法

    2024-05-14 18:18:16       23 阅读