android-sdk
android-sdk copied to clipboard
SpotifyConnectionTerminatedException after several minutes
Thanks for your interest in the Spotify App Remote SDK! If you're submitting a bug, please use the following template. If your issue is a feature request, please include your use-case so that we have all the necessary info.
Issue found on 15/04/2020.
SDK Version:
Remote: 0.7.0 Auth: 1.2.3
OS Version:
Android 10 (OnePlus 7 Pro)
Steps to reproduce:
- Log into the app
- The Spotify app on the current device is listening on a Macbook Pro
- Play a playlist on the Macbook Pro
- After several minutes the connection in the app drops (while it is still in the foreground)
This always happens between 5-10 minutes, without fail.
Expected behaviour:
The SDK does not lose connection, or reconnects by itself when losing connection
Actual behaviour:
The connection stops working, and does not reconnect automatically
com.spotify.android.appremote.api.error.SpotifyConnectionTerminatedException
at com.spotify.android.appremote.api.LocalConnector$1.lambda$onConnected$0(LocalConnector.java:88)
at com.spotify.android.appremote.api.-$$Lambda$LocalConnector$1$IbZLttZmA0yUOwLQJq9O0FFxzoA.onConnectionTerminated(Unknown Source:4)
at com.spotify.protocol.client.RemoteWampClient$1.onGoodbye(RemoteWampClient.java:52)
at com.spotify.protocol.client.WampRouterImpl.routeGoodbye(WampRouterImpl.java:107)
at com.spotify.protocol.client.WampRouterImpl.route(WampRouterImpl.java:30)
at com.spotify.protocol.client.AppProtocolCommunicator.onData(AppProtocolCommunicator.java:78)
at com.spotify.android.appremote.internal.RemoteServiceIo.handleMessage(RemoteServiceIo.java:113)
at com.spotify.android.appremote.internal.RemoteServiceIo.access$000(RemoteServiceIo.java:47)
at com.spotify.android.appremote.internal.RemoteServiceIo$IncomingHandler.handleMessage(RemoteServiceIo.java:91)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7695)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
I am not a 100% sure but i think this is intended behavior. From my experience if you use the SDK and play the song from your phone, where the app is installed, you're fine. But as soon as you change the playback device to e.g. your desktop then the "normal" ConnectionTerminatedException timeout kicks in. As you wouldn't have played any song. I used an automatic reconnect mechanism in my app to tackle this:
suspend fun getAppRemote(): SpotifyAppRemote {
if(!initialized) throw IllegalStateException("Spotify not initialized")
if(connectionState == ConnectionState.CONNECTED) return appRemote
return suspendCancellableCoroutine { con ->
suspendFunctionConnectionStateCallbacks.add(Consumer { state ->
when(state){
ConnectionState.CONNECTED -> con.resume(appRemote)
ConnectionState.DISCONNECTED -> con.cancel()
}
})
}
}
override fun onConnected(appRemote: SpotifyAppRemote) {
this.appRemote = appRemote
initialized = true
connectionState = ConnectionState.CONNECTED
callSuspendFunctionStateCallbacks(ConnectionState.CONNECTED)
}
override fun onFailure(throwable: Throwable) {
connectionState = ConnectionState.DISCONNECTED
if(throwable is SpotifyConnectionTerminatedException){
SpotifyAppRemote.connect(context, connectionParams, this)
} else {
Log.e("SpotifyConnection", "Canceling suspend functions")
callSuspendFunctionStateCallbacks(ConnectionState.DISCONNECTED)
}
}
To briefly explain what is happening here. When you need to perform an action like playing a song you call getAppRemote e.g. getAppRemote().playerApi.play(uri)
. This method either returns app remote directly if you are still connected or if not will suspend the function and waits for the onConnect/onFailure method to call callSuspendFunctionStateCallbacks with either ConnectionState.CONNECTED which means connection got restored or with ConnectionState.Failure which means the connection got closed. When successfully connected the subroutine continues otherwise it gets canceled. The only thing you have to do now is to check what kind of exceptions you want to do an automatic reconnect on in the onFailure method. In this case only if its a SpotifyConnectionTerminatedException.
Hope this helps.
@Nimmidev Can't we just have the
if(throwable is SpotifyConnectionTerminatedException) SpotifyAppRemote.connect(context, connectionParams, this)
in the onFailure listener?
I'm mainly using subscribeToPlayerState tho, but the results seemed to be the same, either with a suspend function like your getAppRemote() or with only using the automatic reconnect in onFailure.
My example was mainly for the usage of control methods like play/pause/queue etc. I experienced the PlayerState subscription to be invalid after a disconnect so i had to wrap that class similarly. Are you sure you receive new PlayerState changes after a reconnect without renewing the subscription?
Oh yes I'm resubscribing to the player state each time after a reconnection, and it works without problem. (sorry I should've been more explicit in my first message)
Hello,
Currently I'm reconnecting as well on SpotifyConnectionTerminatedException
. it would be nice to have an option in the SDK to automatically reconnect, until the app closes or the SDK is stopped.
Thanks for the explanation.
I experience the same thing after 10 minutes of inactivity (not playing music from Spotify SDK). I will implement a re-connection mechanism.