kotlin 手机空闲时的Android计时器

xytpbqjk  于 2023-01-21  发布在  Kotlin
关注(0)|答案(1)|浏览(159)

我正在尝试创建一个Android应用程序,每隔几秒钟就会播放一次声音。我希望这个应用程序即使在手机空闲时也能工作。目前,即使手机屏幕关闭,一切都很好。但大约一分钟后,计时器停止工作。一旦屏幕重新打开,错过的声音被快速连续播放。我很难找到正确的术语和概念,以正确地找到解决方案与谷歌。
当我第一次遇到这个问题时,我确保我的服务在后台运行,看起来服务也在后台启用,因为只要屏幕不关闭,一切都工作正常。

用于在后台运行服务的代码:

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    timer.scheduleAtFixedRate(TimeTask(), 0, 100);
    return START_STICKY
}

private inner class TimeTask() : TimerTask() {
     override fun run() {
        sendBroadcast(Intent(TIMER_UPDATED))
     }
}

由于这不起作用,我尝试将服务设置为前台服务。但这也不起作用。(我尝试如here所示)在前台运行服务的代码:

private fun runInBackground() {
        val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel("service", "something")
            } else {
                ""
            }

        val notification: Notification = NotificationCompat.Builder(this, channelId)
            .setContentTitle("title")
            .setContentText("text")
            .setSmallIcon(R.drawable.alert_dark_frame)
            .build()

        startForeground(1, notification)
}

@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(channelId: String, channelName: String): String{
        val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE)
        channel.lightColor = Color.BLUE
        channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
            .createNotificationChannel(channel)
        return channelId
}

我读了一些关于在Android中调度任务的文章。然后找到了AlarmManager,但是我不认为它真的会像我想要的那样工作,因为我必须每100ms调度一次闹钟。官方的doc也声明不应该以这种方式使用它,“处理程序”更合适,但是我很难理解如何用这样的处理程序替换我当前的计时器。我试过实现一些东西,但是失败了。

val updateHandler = Handler()

val runnable = Runnable {
    // some action
}

updateHandler.looper(runnable, 100)
oxalkeyp

oxalkeyp1#

终于解决了我的问题。我以前不明白的东西是一个“wakelock”。它看起来像这样:

val wakeLock: PowerManager.WakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
        newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ShuttleRun::DefaultWakeLock").apply {
            acquire(30*60*1000L)
        }
    }

它基本上只是让设备保持唤醒状态,这并不意味着屏幕是打开的,而是服务可以在后台运行而不受干扰。

相关问题