cjam / react-native-spotify-remote

React Native wrapper around the Spotify Remote SDK
MIT License
253 stars 101 forks source link

The operation couldn’t be completed. Connection refused #75

Open yingtao-futurewonder opened 4 years ago

yingtao-futurewonder commented 4 years ago

Below is my code. I got accessToken but when I call SpotifyRemote.connect(session.accessToken), I got this error

Possible Unhandled Promise Rejection (id: 2): Error: Connection attempt failed. Stream error. The operation couldn’t be completed. Connection refused

        SpotifyAuth.getSession().then((session) => {
        if (session != undefined && session.accessToken != undefined) {
            SpotifyRemote
            .connect(session.accessToken)
            .then(() => {
                SpotifyRemote.playUri(`spotify:track:${songId}`);
            })
            .catch(this.onError);
        } else {
            console.log("session failed.=============")
        }
yingtao-futurewonder commented 4 years ago

It seems there is something different on the server-side. My server didn't encrypt refresh_token, I don't know if it is the problem. SpotifyAuth works just fine.

yingtao-futurewonder commented 4 years ago

I found if I play a song on my Spotify app, then call SpotifyRemote.connect(session.accessToken), it works.

cjam commented 4 years ago

hey @yingtao-futurewonder , if this is on iOS, it could be that iOS has backgrounded spotify and thus shutting down the message server that this library connects to. Have you seen the playUri configuration option for authorizing/connecting?

yingtao-futurewonder commented 4 years ago

@cjam Thanks for your reply! It works now after I add a playUrl to ApiConfig, but after authenticating, it immediately begins playing the song I set for the playUrl which I don't hope. ( I added SpotifyRemote.pause(); after authenticating, it seems working now)

I found another problem though. When I shut down the Spotify app while playing a Spotify song in my app, then I call SpotifyRemote.connect, it will fail without restarting the Spotify app. Even I start the app again manually, SpotifyRemote.connect still fails. Until I play a song inside the Spotify app, SpotifyRemote.connect works again.

cjam commented 4 years ago

@yingtao-futurewonder glad that was able to help. Did you see in the docs I sent you that if you pass in playUri: "" it will attempt to play from the last position / song? That might be less jarring for your application. As for the second piece. iOS is pretty aggressive with how it backgrounds applications which makes the connection to spotify somewhat challenging to maintain. For the time being, in my app I've been checking to see if a connection has been lost and if it has, re-running the auth->playUri flow to make sure that spotify is started and not backgrounded.

Hope that helps.

yingtao-futurewonder commented 4 years ago

@cjam Thank you so much! it does help!

MrBuggySan commented 4 years ago

@cjam Thank you

MrBuggySan commented 4 years ago

Has anyone been able to connect back to the iOS Spotify client (after it becomes inactive) without switching back to Spotify app again? I thought I'd just cache the token and connect to Spotify client if somehow we get disconnected but it seems like we'd have to open the Spotify app each time.

ryansaam commented 3 years ago

I'm also having this issue. I'm using a real iOS (14.0.1) device. This is my code:

// Api Config object, replace with your own applications client id and urls
const spotifyConfig: ApiConfig = {
    clientID: "my_id",
    redirectURL: "spotify-ios-quick-start://spotify-login-callback",
    // tokenRefreshURL: "SPOTIFY_TOKEN_REFRESH_URL",
  // tokenSwapURL: "SPOTIFY_TOKEN_SWAP_URL",
  playURI: "",
    scopes: [ApiScope.AppRemoteControlScope, ApiScope.UserFollowReadScope]
}

// Initialize the library and connect the Remote
// then play an epic song
async function playEpicSong(){
    try{
    const session = await SpotifyAuth.authorize(spotifyConfig)
    console.log(session)
        await SpotifyRemote.connect(session.accessToken);
        await SpotifyRemote.playUri("");
    await SpotifyRemote.seek(58000);
    }catch(err){
        console.error("Couldn't authorize with or connect to Spotify",err)
    }
}

and the error is the same as OP.

cjam commented 3 years ago

@ryansaam Out of curiosity. Is spotify closed or open when you try to run your code? In the past I've found that closing Spotify and allowing the auth flow to open it back up has worked. Not that I think it's a good solution to this problem, just more thoughts in terms of troubleshooting.

cjam commented 3 years ago

Has anyone been able to connect back to the iOS Spotify client (after it becomes inactive) without switching back to Spotify app again? I thought I'd just cache the token and connect to Spotify client if somehow we get disconnected but it seems like we'd have to open the Spotify app each time.

@MrBuggySan yea some of the issues being faced here are at the iOS level. iOS aggressively backgrounds apps. In this case, when spotify is paused, iOS will background it within about 15-30 s from the time that it is no longer using the background audio. When iOS backgrounds spotify, it kills spotify's message server that their SDK is based off of.

One super hacky idea that I had for my app was to listen to the player state change events and detect when spotify is paused. When you know that spotify is paused, periodically (before iOS has the chance to background spotify) Play and then immediately Pause, ideally it would be so short that the user wouldn't even here it. If this wasn't possible, another thought is to play silence https://open.spotify.com/artist/1fbo6ce8Pg6ZPWlpE3OkfQ to keep spotify from backgrounding. The downside to the silent track is that it would disrupt the current playing context and it will also skew the users popular tracks likely eventually mucking up the suggestions that spotify gives them.

In the ideal scenario, Spotify would prevent itself from being backgrounded if there was an app connected via its remote SDK. For performance / battery life optimizations and App Store compliance they wouldn't want to do this all of the time but it seems reasonable that they could keep their app alive by some means if a client is connected.

It sadly feels like the Spotify iOS sdk is not receiving updates which is sad, I'd love to make this library more robust but without some support from their end it's pretty tough.

Anyways, I digress.

ryansaam commented 3 years ago

@ryansaam Out of curiosity. Is spotify closed or open when you try to run your code? In the past I've found that closing Spotify and allowing the auth flow to open it back up has worked. Not that I think it's a good solution to this problem, just more thoughts in terms of troubleshooting.

Yeah I tried a combination of that and it didn't work. So to answer your question I tried both.

@cjam You think it could be something to do with this redirectURL: "spotify-ios-quick-start://spotify-login-callback" provided by Spotify?

cjam commented 3 years ago

Hey @ryansaam, ah yes that would likely be it. Please look at the docs here: for setting up your iOS app. You basically need to register a callback URI with your app in the spotify dev dashboard. Then you need to add that URL to the info.plist under schemes so that iOS will know to open your app when it gets that URL scheme.

ryansaam commented 3 years ago

@cjam You didn't include the link for the docs. I assume you were talking about the docs for this library?

cjam commented 3 years ago

My bad. Here's the docs you'll need https://developer.spotify.com/documentation/ios/quick-start/

ryansaam commented 3 years ago

I got this to work. Just to clarify I had Spotify's redirect url, spotify-ios-quick-start://spotify-login-callback, already white-listed in my developer console. What solved it for me was these parts of the Spotify iOS Docs

Configure Info.plist Set -ObjC Linker Flag Add Bridging Header

After following them I was able to use react-native-spotify-remote library to play a song as in the setup guide for this library. It works regardless of the Spotify app being opened or closed.

Weird bug/behavior though is if I close the Spotify App and try to reconnect with this library I get the same OP error. Killing my app and reopening resolves this for me.

cjam commented 3 years ago

yea, they're are definitely some issues there that I've noticed, but I haven't been able to pin down if the cause lives in this library or Spotify's

mguay22 commented 3 years ago

I ended up going with your first suggestion @cjam - looks something like this:

async pause() {
    await SpotifyRemote.pause();
    if (this.pauseInterval) {
      clearInterval(this.pauseInterval);
    }
    this.pauseInterval = setInterval(async () => {
      await SpotifyRemote.resume();
      await SpotifyRemote.pause();
    }, 15000);
}

async play(songUri: string) {
    if (this.pauseInterval) {
      clearInterval(this.pauseInterval);
    }
    await SpotifyRemote.playUri(songUri);
}

Works like a charm...

sikky99 commented 2 years ago

I ended up going with your first suggestion @cjam - looks something like this:

async pause() {
    await SpotifyRemote.pause();
    if (this.pauseInterval) {
      clearInterval(this.pauseInterval);
    }
    this.pauseInterval = setInterval(async () => {
      await SpotifyRemote.resume();
      await SpotifyRemote.pause();
    }, 15000);
}

async play(songUri: string) {
    if (this.pauseInterval) {
      clearInterval(this.pauseInterval);
    }
    await SpotifyRemote.playUri(songUri);
}

Works like a charm... This works but do you have any other solution ?.