首页 > 解决方案 > 如何停止在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)

    }
}

标签: androidbroadcastreceiverandroid-broadcastandroid-workmanager

解决方案


您可以尝试保持您workRequest.idAudioInputBroadcastReceiver状态,如果断开连接,您可以停止这项工作。如果您只想完成音频工作,我认为取消所有正在运行的工作是一种不好的做法。

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) }
        }
    }
...

推荐阅读