android - 如何停止在android上运行worker?
问题描述
我创建了一个在连接音频插孔上运行的工作人员,但我无法在广播接收器触发的音频插孔断开连接时停止正在运行的工作人员。我想在工作人员的帮助下跟踪耳机使用限制,该限制只会在有耳机连接时触发,并且会在音频插孔/耳机分离时停止工作人员。
这是广播接收器代码
package com.xanjit.focusly.broadcast_receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.work.*
import com.xanjit.focusly.workers.GetHeadsetUsageTimeWorker
import java.sql.Timestamp
import java.time.Duration
class AudioInputBroadcastReceiver : BroadcastReceiver() {
// lateinit var workManager: WorkManager
// lateinit var workRequest: WorkRequest
@RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = intent!!.getIntExtra("state", 0) === 1
val workManager = WorkManager.getInstance(context!!)
if (isConnected) {
var startTime = System.currentTimeMillis()
Toast.makeText(context,"Connected",Toast.LENGTH_SHORT).show()
val data = Data.Builder()
data.putLong("startTime", startTime)
val workRequest = OneTimeWorkRequest.Builder(
GetHeadsetUsageTimeWorker::class.java,
).setInputData(data.build())
.build()
workManager.enqueue(workRequest)
} else {
Toast.makeText(context,"Disconnected",Toast.LENGTH_SHORT).show()
// val data = Data.Builder()
//
// data.putBoolean("isStopped", true)
// val workRequest = OneTimeWorkRequest.Builder(
// GetHeadsetUsageTimeWorker::class.java,
// ).setInputData(data.build()).build()
workManager.cancelAllWork()
}
}
override fun peekService(myContext: Context?, service: Intent?): IBinder {
return super.peekService(myContext, service)
}
}
工人代码
package com.xanjit.focusly.workers
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.media.AudioAttributes
import android.net.Uri
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.work.ListenableWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.xanjit.focusly.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.sql.Timestamp
import kotlin.time.seconds
var TAG = "EarGuard"
class GetHeadsetUsageTimeWorker(context: Context, workerParams: WorkerParameters) : Worker(
context,
workerParams,
) {
@RequiresApi(Build.VERSION_CODES.O)
override fun doWork(): Result {
// Log.d("EarGuard", "StartTime Worker")
var startTime = inputData.getLong("startTime", System.currentTimeMillis())
// var stopped = inputData.getBoolean("isStopped", false)
// if (!isStopped and !stopped) {
// Log.d("EarGuard", "StartTime Worker" + startTime)
Log.d(TAG, isStopped.toString())
Thread {
while (!isStopped) {
Thread.sleep(1000)
var usageTime = System.currentTimeMillis()
usageTime -= startTime
Log.d(TAG, usageTime.toString())
if ((usageTime / 1000) == 5L) {
CoroutineScope(Dispatchers.Main).launch(Dispatchers.Main)
{
// Toast.makeText(
// applicationContext,
// "Time limit exceeded", Toast.LENGTH_LONG
// ).show()
val notificationChannel = NotificationChannel(
"123",
"EarGuard",
NotificationManager.IMPORTANCE_HIGH
)
notificationChannel.description =
"You have exceeded the maximum usage limit of listening on headset"
notificationChannel.name = "EarGuard"
notificationChannel.lockscreenVisibility = 1
notificationChannel.shouldShowLights()
notificationChannel.enableVibration(true)
notificationChannel.setSound(
Uri.parse("R.raw.sad"),
AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build()
)
notificationChannel.shouldVibrate()
var notificationManager =
applicationContext.getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(notificationChannel)
notificationManager.notify(
123, NotificationCompat.Builder(
applicationContext, "123"
).setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(
BitmapFactory.decodeResource(
applicationContext.resources,
R.drawable.ic_launcher_foreground
)
)
.setSound(
Uri.parse("R.raw.sad")
)
.setContentTitle("EarGuard")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentText("You have exceeded the maximum usage limit of listening on headset")
.setAutoCancel(false)
.setChannelId("123")
.build()
)
}
break
}
}
}.start()
// }
return Result.success()
}
// @SuppressLint("RestrictedApi")
// override fun isRunInForeground(): Boolean {
// return super.isRunInForeground()
// }
override fun onStopped() {
Log.d(TAG, "Stopped Worker")
super.onStopped()
}
}
MainActivity.kt
package com.xanjit.focusly
import android.content.*
import android.net.Uri
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.*
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkRequest
import com.xanjit.focusly.broadcast_receivers.AudioInputBroadcastReceiver
import com.xanjit.focusly.services.CustomService
import com.xanjit.focusly.workers.GetHeadsetUsageTimeWorker
import java.lang.Exception
class MainActivity : ComponentActivity() {
lateinit var receiver: BroadcastReceiver
var TAG = "EarGuard"
lateinit var workManager: WorkManager
lateinit var workRequest: WorkRequest
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
receiver = AudioInputBroadcastReceiver()
setContent {
Surface() {
Scaffold(
topBar = {
TopAppBar() {
}
}
) {
}
}
}
}
override fun onStart() {
super.onStart()
var intentFilter = IntentFilter("android.intent.action.HEADSET_PLUG");
registerReceiver(receiver, intentFilter)
}
}
解决方案
您可以尝试保持您workRequest.id
的AudioInputBroadcastReceiver
状态,如果断开连接,您可以停止这项工作。如果您只想完成音频工作,我认为取消所有正在运行的工作是一种不好的做法。
cancelAllWork()
取消所有未完成的工作。 使用此方法时要格外小心! 通过调用它,您可能会影响代码库中的其他模块或库。强烈建议您使用您可以使用的其他取消方法之一。
class AudioInputBroadcastReceiver : BroadcastReceiver() {
val workerRequestId: UUID? = null
@RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = intent!!.getIntExtra("state", 0) === 1
val workManager = WorkManager.getInstance(context!!)
if (isConnected) {
....
val workRequest = OneTimeWorkRequest.Builder(
GetHeadsetUsageTimeWorker::class.java,
).setInputData(data.build()).build()
workerRequestId = workRequest.id
workManager.enqueue(workRequest)
} else {
Toast.makeText(context,"Disconnected",Toast.LENGTH_SHORT).show()
workerRequestId?.let { workManager.cancelWorkById(it) }
}
}
...
推荐阅读
- django - 使用 Django 实现多对多(无重复)
- python - Python解释器抱怨在当前进程完成引导阶段之前尝试启动新进程
- sql-server - 使用 group by 根据最大其他列获取顶部列?
- c++ - 有没有办法使用 C++ 实时阅读文本?
- laravel - 如何在控制器之间创建验证码会话
- python - python pandas:将字典转换为长格式,计数基于字符串变量的不同值
- c# - 在 C# 中指向或反射到对象
- python - 使用 matplotlib 制作堆栈图时出现“Keyerror”
- ios - 未调用具有 Firebase 消息回调的 Flutter 插件
- yocto - 构建 gcc-cross 失败,没有提供“gcc-cross”