Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Currently-selected song begins playing when connecting to Spotify on iOS #86

Open
mcookhome opened this issue Apr 4, 2021 · 13 comments · Fixed by #94
Open

Currently-selected song begins playing when connecting to Spotify on iOS #86

mcookhome opened this issue Apr 4, 2021 · 13 comments · Fixed by #94
Labels
enhancement New feature or request iOS Specific for iOS SPTSessionManager

Comments

@mcookhome
Copy link

Describe the bug

When opening an app integrating the SDK on iOS (for two iPhones with different versions), the Spotify app opens and plays the current song. Using breakpoints, I was able to pinpoint the last line of code before the Spotify app was opened to within the SDK here.

To Reproduce
Steps to reproduce the behavior:

  1. Connect from your app to Spotify using these lines of the SDK on iOS
  2. Accept Spotify permissions for your app, if this is the first login (if not, the permissions dialog will not show)
  3. Your currently selected song will start playing,
  4. Focus will be toggled back to your app, with music still playing

Expected behavior
I would hope for the app to be able to connect to Spotify without opening the app and toggling the play state. However, according to @fotiDim, the Spotify app must still be opened regardless - but the music being played should be fixable.

Screenshots

video-1617059678.mp4

Smartphone (please complete the following information):

  • Device: two different iphones of differing iOS versions

Additional context
Slack conversation

@fotiDim fotiDim added iOS Specific for iOS enhancement New feature or request labels Apr 5, 2021
@fotiDim
Copy link
Collaborator

fotiDim commented Apr 10, 2021

@mcookhome this is "potentially" fixed now. Allow me to clarify "potentially"...
The native Spotify iOS SDK supports two authentication methods,built-in authorization flow and SPTSessionManager. This library uses exclusively built-in authorization flow for reasons of simplicity and consistency with Android and Web.

When using the built-in authorization flow Spotify will be suspended if it doesn't start playing media immediately. In the native iOS SDK documentation it states:

Why does music need to be playing to connect with SPTAppRemote?
Music must be playing when you connect with SPTAppRemote to ensure the Spotify app is not suspended in the background. iOS applications cannot stay alive in the background indefinitely unless they are actively doing something like navigation or playing music.

There is an official way to mitigate that and that is to use SPTSessionManager. However this is a way more complicated setup as it requires you to setup your own backend component to perform authorization code swap and token refreshing. I have used it in the past (in native code) and I believe the gains do not justify the effort.

Having said that you can try this small workaround that might solve your problem. In version 2.1.0 of the package there is a spotifyUri argument in connectToSpotifyRemote(...) . You can pass an invalid Spotify URI (e.g. spotify:track:58kNJana4w5BIjlZE2wq5r) and then Spotify connects without playing music, at least according to my tests. This is not officially supported so it can fail or stop working at any moment.

@mcookhome
Copy link
Author

Awesome!! Thanks so much @fotiDim - can I start using version 2.1.0 now, or do I need to wait for a release? I only see version 2.0.0 on the pub.dev page:
image

@fotiDim
Copy link
Collaborator

fotiDim commented Apr 16, 2021

No need to wait. You can use this in your pub spec.yaml to get the latest version from the repo.

spotify_sdk:
  git:
    url: https://github.com/brim-borium/spotify_sdk

Let me know how it works for you.

@mcookhome
Copy link
Author

Hey @fotiDim, unfortunately I'm finding the bug to still occur:

Here's a snippet of my pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  spotify_sdk:
    git:
      url: https://github.com/brim-borium/spotify_sdk
  get_it: ^5.0.4

I've run pod install, pod upgrade, re-installed my app multiple times on the target phone, and each time it still plays the targeted song when opening my app. I simply don't know what I'm doing wrong.

I had also tried using version 2.1.0 which had said it offered some of the other changes you'd said you'd made - and that didn't work either. If you want, I'll attach another video of it not working, but I'm not sure if it will help. Do you know what I could be doing wrong?

@mcookhome
Copy link
Author

Regardless, I don't think issue should remain closed, as it's still an active issue

@fotiDim fotiDim reopened this May 11, 2021
@fotiDim
Copy link
Collaborator

fotiDim commented May 11, 2021

@mcookhome do you pass a spotifyUri? If yes which one?

@mcookhome
Copy link
Author

I don't pass a spotifyUri at all at the moment. here's the snippet of dart code where I connect to spotify:

  Future<void> connectToSpotifyRemoteWithCreds(
      Map<String, dynamic> creds) async {
    try {
      _container.sharedPrefs
          .getToken()
          .then((token) => connectToSpotifyRemoteWithToken(token, creds));
    } on PlatformException catch (e) {
      setStatus(e.code, message: e.message);
    } on MissingPluginException {
      setStatus('not implemented');
    }
  }

  Future<void> connectToSpotifyRemoteWithToken(
      String token, Map<String, dynamic> creds) async {
    if (token == null) {
      var result = await SpotifySdk.connectToSpotifyRemote(
          clientId: creds["spotify_client_id"],
          redirectUrl: creds["spotify_redirect_url"]);
      setStatus(result
          ? 'connect to spotify successful'
          : 'connect to spotify failed');
      getAuthenticationTokenWithCreds(creds);
      return result;
    } else {
      var result = await SpotifySdk.connectToSpotifyRemote(
          clientId: creds["spotify_client_id"],
          redirectUrl: creds["spotify_redirect_url"],
          accessToken: token);
      setStatus(result
          ? 'connect to spotify successful'
          : 'connect to spotify failed');
      return result;
    }
  }

In that snippet, the creds parameter is populated with my spotify client ID and redirect URI. otherwise, I'm not passing a URI at all.

@mcookhome
Copy link
Author

You can also see my attempts at passing an accessToken which we talked about in Slack - but it didn't successfully allow me to avoid opening the app, so I will likely eventually remove that as well.

@fotiDim
Copy link
Collaborator

fotiDim commented May 15, 2021

I don't pass a spotifyUri at all at the moment. here's the snippet of dart code where I connect to spotify:

  Future<void> connectToSpotifyRemoteWithCreds(
      Map<String, dynamic> creds) async {
    try {
      _container.sharedPrefs
          .getToken()
          .then((token) => connectToSpotifyRemoteWithToken(token, creds));
    } on PlatformException catch (e) {
      setStatus(e.code, message: e.message);
    } on MissingPluginException {
      setStatus('not implemented');
    }
  }

  Future<void> connectToSpotifyRemoteWithToken(
      String token, Map<String, dynamic> creds) async {
    if (token == null) {
      var result = await SpotifySdk.connectToSpotifyRemote(
          clientId: creds["spotify_client_id"],
          redirectUrl: creds["spotify_redirect_url"]);
      setStatus(result
          ? 'connect to spotify successful'
          : 'connect to spotify failed');
      getAuthenticationTokenWithCreds(creds);
      return result;
    } else {
      var result = await SpotifySdk.connectToSpotifyRemote(
          clientId: creds["spotify_client_id"],
          redirectUrl: creds["spotify_redirect_url"],
          accessToken: token);
      setStatus(result
          ? 'connect to spotify successful'
          : 'connect to spotify failed');
      return result;
    }
  }

In that snippet, the creds parameter is populated with my spotify client ID and redirect URI. otherwise, I'm not passing a URI at all.

You need to pass a SpotifyURI:

In version 2.1.0 of the package there is a spotifyUri argument in connectToSpotifyRemote(...) . You can pass an invalid Spotify URI (e.g. spotify:track:58kNJana4w5BIjlZE2wq5r) and then Spotify connects without playing music, at least according to my tests. This is not officially supported so it can fail or stop working at any moment.

For the other issue:

  • Are you sure you're using 2.1.0 version of the package?
  • How do you obtain the accessToken that you are eventually passing?

@mcookhome
Copy link
Author

mcookhome commented May 15, 2021

You need to pass a SpotifyURI:

The problem with that is that if I pass an invalid spotifyUri, then if the music is currently playing on the user's Spotify app, then their music will stop. It will be the inverse of the problem I'm trying to solve. I'd like to be able to check the play state to determine whether or not I'll need to pass the spotifyUri, but to check the play state, I need to connect to the spotify SDK...

Is there any way that the SDK can check the user's current player state, pass the uri to the connect function if the user is not playing music, and not pass the uri to the connect function if the user is playing music?

My desired functionality of the connect method would be as follows:

  • If music is playing, continue playing unaffected
  • If music is not playing, do not play at all

If this is impossible that's fine, but I just wasn't sure if I was clear.

@fotiDim
Copy link
Collaborator

fotiDim commented May 15, 2021

I see. There is this native iOS SDK method that we could expose:

/**
 * Checks if the Spotify app is active on the user's device. You can use this to determine if maybe you should prompt
 * the user to connect to Spotify (because you know they are already using Spotify if it is active). The Spotify app
 * will be considered active if music is playing or the app is active in the background.
 *
 * @param completion Completion block for determining the result of the check. YES if Spotify is active, othewise NO.
 */
+ (void)checkIfSpotifyAppIsActive:(void (^)(BOOL active))completion;

I believe it provides the information that you need. However automating spotifyUri using the logic you described, I believe should be done by the end developer and not this SDK as the native SDK also does not do this.

@fotiDim
Copy link
Collaborator

fotiDim commented May 16, 2021

@mcookhome regarding the accessToken issue I reverified that it works. If it does not work for you you might be doing something wrong. If the issue persists please open another issue to keep the discussions separate.

@ViktorKirjanov
Copy link

any updates?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request iOS Specific for iOS SPTSessionManager
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants