【问题标题】:Disable service restart on button click单击按钮时禁用服务重启
【发布时间】:2021-03-18 02:30:21
【问题描述】:

我启动一个前台服务,当用户单击按钮时下载文件。现在发生的情况是,当我再次单击该按钮时,服务内的线程第二次启动,并且我在通知中看到两个线程的进度都已更新(在线程之间跳转)。

如果第一个线程正在运行,如何防止启动第二个线程,如果服务仍在运行,如何防止调用startService()onStartCommand()

class ForegroundService : Service() {
    private val CHANNEL_ID = "ForegroundService Kotlin"

    companion object {

        fun startService(context: Context, message: String) {
            val startIntent = Intent(context, ForegroundService::class.java)
            startIntent.putExtra("inputExtra", message)
            ContextCompat.startForegroundService(context, startIntent)
        }

        fun stopService(context: Context) {
            val stopIntent = Intent(context, ForegroundService::class.java)
            context.stopService(stopIntent)
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {


        val input = intent?.getStringExtra("inputExtra")
        createNotificationChannel()
        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this,
            0, notificationIntent, 0
        )

        //start doing some work and update the notification
        //when done calling stopSelf();

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Foreground Service Kotlin Example")
            .setContentText(input)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .build()

        startForeground(1, notification)

        return START_NOT_STICKY
    }

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

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                CHANNEL_ID, "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            )

            val manager = getSystemService(NotificationManager::class.java)
            manager!!.createNotificationChannel(serviceChannel)
        }
    }
}

打电话

buttonGoNext.setOnClickListener {
    val intent = Intent(this, DownloadActivity::class.java)
    startActivity(intent)
}

【问题讨论】:

  • 在本地保存通知通道id并检查是否已经有使用该id的通知运行,只需将其删除或不启动新任务

标签: android kotlin android-service


【解决方案1】:

在你的 startService 函数中,你想检查这个服务是否已经在运行。如果服务已经在运行,您可以提前返回。已经有多个SO threads 涉及如何找出服务是否已在运行的问题。

为了更好地控制您的后台工作,我建议您熟悉 Android 的 WorkManager。您可以使用 KEEP 策略创建 unique OneTimeWorkRequest,这也可以解决问题。

此外,您应该在代码中更好地分离您的职责。你的 ForegroundService 类目前一次处理了太多的事情。您创建通知渠道,显示通知,并且可能还想处理您描述的行为。将这些关注点分开并将它们转移到不同的类通常是一种很好的做法。这也使其更具可测试性。

【讨论】:

  • 我认为WorkManager 在所有设备上并不可靠。见this
猜你喜欢
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 2012-04-07
相关资源
最近更新 更多