Q:

viewModelScope not cancelled

After watching Sean's explanation on Android (Google I/O'19) I've tried the same:
init{
    viewModelScope.launch {
        Timber.i("coroutine awake")
        while (true){
            delay(2_000)
            Timber.i("another round trip")
        }
    }
}

Unfortunately onCleared it's called when the activity is killed but not when it's put in background ("when we move away from the Activity...", background is "moving away" imho ^^). 
And I get the following output:
> ---- Activity in Foreground
> 12:41:10.195  TEST: coroutine awake
> 12:41:12.215  TEST: another round trip
> 12:41:14.231  TEST: another round trip
> 12:41:16.245  TEST: another round trip
> 12:41:18.259  TEST: another round trip
> 12:41:20.270  TEST: another round trip
> ----- Activity in Background (on onCleared not fired)
> 12:41:22.283  TEST: another round trip
> 12:41:24.303  TEST: another round trip
> 12:41:26.320  TEST: another round trip
> 12:41:28.353  TEST: another round trip
> 12:41:30.361  TEST: another round trip
> ----- Activity in Foreground
> 12:41:30.369  TEST: coroutine awake

How can I solve this? 
1 - Move the code from init to a suspend fun start() called by the activity inside a lifecycleScope.launchWhenStarted?   
I get the same result.  I thought lifecycleScope would cancel its child coroutines when it went to background, but I get the same Timber output with this approach.  
2 - Change my ViewModel code to:
private lateinit var job: Job

suspend fun startEmitting() {
    job = viewModelScope.launch {
        Timber.i("coroutine awake")
        while (true){
            delay(2_000)
            Timber.i("another round trip")
        }
    }
}
fun cancelJob(){
    if(job.isActive){
        job.cancel()
    }
}

And, in my Activity:
override fun onResume() {
    super.onResume()
    lifecycleScope.launch {
        viewModel.startEmitting()
    }
}
override fun onPause() {
    super.onPause()
    viewModel.cancelJob()
}

Well it works but isn't the viewModelScope purpose to manage the CoroutineScope for me?  I hate this cancelJob logic. 
What's the best approach to deal with this?  

A:

Kotlin can't cancel an infinite operation for you.  You need to call isActive somewhere.  For example: while(isActive).