https://kotlinlang.org logo
Title
o

Oleh Ponomarenko

03/07/2019, 10:07 AM
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

Oleh Ponomarenko

03/07/2019, 10:18 AM
Here is my 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

gildor

03/07/2019, 10:27 AM
To make it endless just wrap it to while(true)
o

Oleh Ponomarenko

03/07/2019, 10:29 AM
How can I stop my task in 30 seconds?
g

gildor

03/07/2019, 10:52 AM
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

Oleh Ponomarenko

03/07/2019, 10:55 AM
yes, i have
g

gildor

03/07/2019, 10:55 AM
So just use delay(30, Seconds) after start
o

Oleh Ponomarenko

03/07/2019, 10:56 AM
Is it correct way:
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

gildor

03/07/2019, 10:59 AM
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

Oleh Ponomarenko

03/07/2019, 11:09 AM
Everything works fine, thanks
s

sitepodmatt

03/07/2019, 1:36 PM
if bluetooth scanner becomes null which you seem to suggest is possible it will just continue looping ?
b

bdawg.io

03/07/2019, 4:37 PM
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

Oleh Ponomarenko

03/07/2019, 4:44 PM
Yes, sometimes I use cancellation, when I switch between running in Service and usual mode.
g

gildor

03/07/2019, 5:01 PM
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