Hello guys! Please help me with Coroutines. I need...
# coroutines
o
Hello guys! Please help me with Coroutines. I need to implement this: 1. Run my task in background mode 2. Stop the task in 30 seconds 3. Delay 10 seconds. 4. Repeat my cycle (1-3 points) infinitely https://prntscr.com/mu5xin (detailed on a picture)
o
Here is my code:
Copy code
CoroutineScope(Dispatchers.Default).launch {
            BluetoothAdapter.getDefaultAdapter()?.takeIf { !it.isEnabled }?.enable()

            if (bluetoothScanner == null) {
                delay(3000)
                bluetoothScanner = BluetoothAdapter.getDefaultAdapter()?.bluetoothLeScanner
            }
            try {
                bluetoothScanner?.startScan(filters, settings, callback)
            } catch (e: IllegalStateException) {
                Log.e(TAG, e.localizedMessage)
            }
        }
Can you help to implement this due to my picture? I need to scan for 30 seconds, then stop for 10 seconds, then resume to scanning for 30 seconds. This cycle should be endless.
g
To make it endless just wrap it to while(true)
o
How can I stop my task in 30 seconds?
g
See my first comment
Use withTimeout and wrap it to try/catch to catch cancellation exception, this is probably the easiest way, but you can check implementation and write own similar coroutine builder that doesn't throw exception on timeout
It also depends on how this scanning works
I see that you just start it and pass callback, in this case you probably have some stopScanning method
o
yes, i have
g
So just use delay(30, Seconds) after start
o
Is it correct way:
Copy code
CoroutineScope(Dispatchers.Default).launch {
            while (true) {
                val timeout = 20000L
                try {
                    Log.d(TAG, "starting")
                    bluetoothScanner?.startScan(filters, settings, callback)
                    withTimeout(timeout) {
                        Log.d(TAG, "stop scan")
                        bluetoothScanner?.stopScan(callback)
                    }
                    delay(10000)
                    Log.d(TAG, "Pause works fine")
                } catch (e: Exception) {
                    Log.e(TAG, e.localizedMessage)
                }
            }
        }
?
g
You don't need withTimeout in this case
Delay is enough
withTimeout make sense only if you have some suspend operation that should be cancelled on timeout, in this case you just call non-suspend method
Just a note about your code: explicitly passing default dispatcher is most probably redundant
Just want to add that correctness of this code highly depends on how bluetoothScanner works, but if it common call back API this approach should work
o
Everything works fine, thanks
s
if bluetooth scanner becomes null which you seem to suggest is possible it will just continue looping ?
b
Something to note is that
withTimeout
is collaborative cancellation. If
stopScan
is a blocking method that takes 25 seconds, it won’t be cancelled at the 20 second timeout.
o
Yes, sometimes I use cancellation, when I switch between running in Service and usual mode.
g
this method doesn’t look as blocking, because callback is passed to startScan and to stopScan, most probably it’s some non-blocking method that returns immediately