Search code examples
androidspotifylifecycle

Spotify: save playback state information


I am writing an android application based off of the demo activity here: DemoActivity.java

I want to be able to flip the screen of an android device (portrait to landscape or vice versa) and keep the user logged in and the music playing. Currently I am able to keep the user logged in, but I am stuck on how to save the playback state.

In my onCreate:

if(savedInstanceState != null) {
        String accessToken = savedInstanceState.getString("accesstoken");
        Config player_Config = new Config(this, accessToken, CLIENT_ID);
        setPlayer(player_Config);
        mCurrentPlaybackState = savedInstanceState.getParcelable("playbackstate");
    }

my onSaveInstanceState:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putString("accesstoken", accessToken);
    savedInstanceState.putParcelable("playbackstate", mCurrentPlaybackState);
    super.onSaveInstanceState(savedInstanceState);
}

my setPlayer (doesn't include authentication because user would already be logged in):

    public void setPlayer(Config player_Config) {
    Spotify.getPlayer(player_Config, this, new SpotifyPlayer.InitializationObserver() {

        @Override
        public void onInitialized(SpotifyPlayer spotifyPlayer) {
            myPlayer = spotifyPlayer;
            myPlayer.addConnectionStateCallback(HostPartyActivity.this);
            myPlayer.addNotificationCallback(HostPartyActivity.this);
            updateUIElements();
        }

        @Override
        public void onError(Throwable throwable) {
            Log.e("HostPartyActivity", "Could not initialize player: " + throwable.getMessage());
        }
    });
}

Sample situation of my problem:

  • User presses "Log in" button and logs into Spotify account
  • User presses "Play" button and a Spotify track begins to play
  • User flips device from portrait to landscape
  • App automatically logs in the User based saved data
  • Spotify track stops playing (should keep playing at saved time)

Thank you for any help.


Solution

  • After some research I think I've worked out how to save the necessary playback state information. in my onCreate:

    if(savedInstanceState != null) { //restore instance
            accessToken = savedInstanceState.getString("accesstoken");
            if(accessToken != null) { //user was logged in
                Config player_Config = new Config(this, accessToken, CLIENT_ID);
                setPlayer(player_Config);
                /*
                * player is destroyed when new activity is started, so I need to get a new authentication code
                * for the new activity's player
                */
    
                myCurrentPlaybackState = savedInstanceState.getParcelable("playbackstate");
                myMetadata = savedInstanceState.getParcelable("metadata");
                if(myCurrentPlaybackState != null && myMetadata != null) { //user has played a song
                    myPlayer.playUri(myMetadata.currentTrack.uri, (int)myMetadata.currentTrack.indexInContext, (int)myCurrentPlaybackState.positionMs);
                }
            }
        }
    

    my onSaveInstanceState:

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putString("accesstoken", accessToken);
        if(myCurrentPlaybackState != null && myMetadata != null) {
            savedInstanceState.putParcelable("playbackstate", myCurrentPlaybackState);
            savedInstanceState.putParcelable("metadata", myMetadata);
        }
        super.onSaveInstanceState(savedInstanceState);
    }
    

    my setPlayer:

        public void setPlayer(Config player_Config) {
        myPlayer = Spotify.getPlayer(player_Config, this, new SpotifyPlayer.InitializationObserver() {
    
            @Override
            public void onInitialized(SpotifyPlayer spotifyPlayer) {
                myPlayer.addConnectionStateCallback(HostPartyActivity.this);
                myPlayer.addNotificationCallback(HostPartyActivity.this);
                updateUIElements();
            }
    
            @Override
            public void onError(Throwable throwable) {
                Log.e("HostPartyActivity", "Could not initialize player: " + throwable.getMessage());
            }
        });
    }
    

    With this code, the new activity generated by flipping my device can access the playback state and metadata info from the previous activity. However, the music track still won't resume playing in the new activity because when the old activity is destroyed it also destroys the player:

        @Override
    protected void onDestroy() {
        Spotify.destroyPlayer(this);
        super.onDestroy();
    }
    

    And I can't re access this authenticated player, even if I create a new one using the same access token used to create the original (error: Could not initialize player: player already shut down). How to achieve that is a separate question.