Control playback of the Spotify app from another A

2019-03-30 18:09发布

问题:

Is it possible to control playback of the Spotify app from within another Android app? I'm only looking for track skipping functionality (forward and backward).

I'm aware of the Spotify Android SDK, but it seems to only allow skipping of tracks played by the SDK:

com.spotify.sdk.android.playback.NativeSpotifyException: Failed SpPlaybackSkipToPrev with  error code 14 (The operation is not supported if the device is not the active playback device)

To clarify, both the actual Spotify app, and my own app are running on the same device

回答1:

Quick answer - No, this isn't possible.



回答2:

Here's how to do it:

This will try to play/pause Spotify. If it's not running it will start it and make it start playing.

    public void nextSong() {

    int keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;

    if (!isSpotifyRunning()) {
        startMusicPlayer();
    }

    Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
    intent.setPackage("com.spotify.music");
    synchronized (this) {
        intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
        getContext().sendOrderedBroadcast(intent, null);

        intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
        getContext().sendOrderedBroadcast(intent, null);
    }
}

public void playPauseMusic() {
    int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;

    if (!mAudioManager.isMusicActive() && !isSpotifyRunning()) {
        startMusicPlayer();
    }

    Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
    i.setPackage("com.spotify.music");
    synchronized (this) {
        i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
        getContext().sendOrderedBroadcast(i, null);

        i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
        getContext().sendOrderedBroadcast(i, null);
    }
}

private void startMusicPlayer() {
    Intent startPlayer = new Intent(Intent.ACTION_MAIN);
    startPlayer.setPackage("com.spotify.music");
    startPlayer.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    getContext().startActivity(startPlayer);

    if (mMusicPlayerStartTimer != null) {
        mMusicPlayerStartTimer.cancel();
    }

    mMusicPlayerStartTimer = new Timer("MusicPlayerStartTimer", true);
    mMusicPlayerStartTimer.schedule(new MusicPlayerStartTimerTask(), DateUtils.SECOND_IN_MILLIS, DateUtils.SECOND_IN_MILLIS);
}

private boolean isSpotifyRunning() {
    Process ps = null;
    try {
        String[] cmd = {
                "sh",
                "-c",
                "ps | grep com.spotify.music"
        };

        ps = Runtime.getRuntime().exec(cmd);
        ps.waitFor();

        return ps.exitValue() == 0;
    } catch (IOException e) {
        Log.e(DEBUG_TAG, "Could not execute ps", e);
    } catch (InterruptedException e) {
        Log.e(DEBUG_TAG, "Could not execute ps", e);
    } finally {
        if (ps != null) {
            ps.destroy();
        }
    }

    return false;
}

private class MusicPlayerStartTimerTask extends TimerTask {
    @Override
    public void run() {
        if (isSpotifyRunning()) {
            playPauseMusic(null);
            cancel();
        }
    }
}

EDIT: Added full example code



回答3:

Yes, you can control playback using the RemoteController classes, or if using Lollipop, the MediaController classes, or if supporting L and earlier, then the MediaControllerCompat classes.

Then perform dispatchMediaButtonEvent() with KEYCODE_MEDIA_NEXT.