Search code examples
kotlinmediawear-oswear-os-tiles

Wear OS Tiles and Media Service


The Wear OS tiles example is great, not so much of an issue but how would one start the background media service that play the songs selected in the primary app, when every I try to start the service, I get the following error. The is no UI thread to reference and the documentation only has to methods for onclick, LoadAction and LaunchAction.

override fun onTileRequest(request: TileRequest) = serviceScope.future {
when(request.state!!.lastClickableId){
"play"-> playClicked()
}....

suspend fun playClicked(){

    try {
        // Convert the asynchronous callback to a suspending coroutine
        suspendCancellableCoroutine<Unit> { cont ->
            mMediaBrowserCompat = MediaBrowserCompat(
                applicationContext, ComponentName(applicationContext, MusicService::class.java),
                mMediaBrowserCompatConnectionCallback, null
            )
            mMediaBrowserCompat!!.connect()

        }
    }catch (e:Exception){
        e.printStackTrace()
    } finally {
      mMediaBrowserCompat!!.disconnect()
    }
}

ERROR

java.lang.RuntimeException: Can't create handler inside thread Thread[DefaultDispatcher-worker-1,5,main] that has not called Looper.prepare()

Solution

  • Responding to the answer above, the serviceScope.future creates a CoroutineScope that will cause the future returned to the service to wait for all child jobs to complete.

    If you want to have it run detached from the onTileRequest call, you can run the following, which will launch a new job inside the application GlobalScope and let the onTileRequest return immediately.

    "play" -> GlobalScope.launch { 
    
    }
    

    The benefit to this is that you don't throw a third concurrency model into the mix, ListenableFutures, Coroutines, and now Handler. LF and Coroutines are meant to avoid you having to resort to a third concurrency option.