Using Spotify Android SDK in Unity

Unity 2022.3.14f1 + spotify-app-remote-release-0.8.0

Seeing there is no tutorial about this and I’ve been recently playing with this so hopefully this would help someone like myself πŸ™‚

In my case I’m using AppRemote only as I only want to grab Spotify’s current playing track information on my Android app + trigger song playing. If you are also going to use the Spotify Android SDK, make sure you have installed latest Spotify app on your Android device.

  1. Unity Project Setup
  2. Install Spotify Android SDK
  3. From and to Unity C# script and Java
  4. Spotify Android Media Notifications

Unity Project Setup

  1. Create a new Unity project, of course install the Android platform module too
  2. Once your project is opened
  3. TopMenu > File > Build Settings > Android > click Switch Platform
  4. TopMenu > Edit > Project Settings > Player, enter your own names
  5. Scroll to below, under Other Settings, note the default package name
  6. Scroll to below, under Publish Settings, click Keystore Manager and create a new keystore file
  7. Use the keystore file on the Publish Settings
    (In the future when you open the project again, in order to make a build, you will need to type the passwords again)
  8. TopMenu > File > Save Project
  9. TopMenu > File > Build Settings > Build Settings >
    on Run Device > select your connected Android device
    check Development Build checkbox and then click Build and Run
  10. This can confirm if your PC and Unity is setup correctly to build Android application

Install Spotify Android SDK

  1. Go to https://developer.spotify.com/documentation/android/tutorials/getting-started
    and follow Register Your App section.
    Fill in your app details like this:
  2. On the app’s Home page, go to Settings page
    Add your package name which is same as the one in Unity Project Settings.

    You will also need the SHA1 fingerprint, to get it:
    On your Windows search, type cmd, then edit following and type:
    • cd C:\your Unity Editor folder path\Data\PlaybackEngines\AndroidPlayer\OpenJDK\bin
    • keytool -list -v -keystore C:\your folder path where the keystore file is\user.keystore -alias yourAlias -storepass yourStorePassword -keypass yourKeyPassword
  3. The settings page should look something like this.
    Note the Client ID on the top.
  4. Go to https://github.com/spotify/android-sdk/releases
  5. Download only spotify-app-remote-release-0.8.0.aar
  6. Put this .aar file in your Unity project’s Assets/Plugins/Android folder
    Create the folders yourself if there isn’t one.
  7. TopMenu > Edit > Project Settings > Player > Publish Settings,
    check Custom Main Manifest and Custom Main Gradle Template
  8. Open and edit the generated mainTemplate.gradle file,
    add implementation "com.google.code.gson:gson:2.6.1" in dependencies
  9. Open and edit the generated AndroidManifest.xml file,
    Change <activity android:name="com.unity3d.player.UnityPlayerActivity"
    To <activity android:name=".MainActivity"
  10. In Assets/Plugins/Android folder, create a file called MainActivity.java, paste the below [Code for MainActivity.java] code to it. Remember to edit the client id!
  11. Make sure you have Spotify app running on your Android device
  12. Build and Run to your Android device.
    If success, on your Android device you should see a Spotify permission agreement screen for your app. Click AGREE. After your app starts, Spotify will start playing songs from the playlist “Feel-Good Indie Rock“. That means the setup is successful! πŸŽ‰
  13. Tips: TopMenu > Window > Package Manager > select Packages: Unity Registry and Install Android Logcat
    TopMenu > Window > Analysis > Android Logcat
    You can also see the related messages from the java script on Logcat
  14. Now you can further edit MainActivity.java to do things you want πŸŽ‰

Code for MainActivity.java
(The original code comes from: Spotify Android SDK documentation)

package com.unity3d.player;

import android.os.Bundle;
import com.unity3d.player.UnityPlayerActivity;
import android.content.Intent;
import android.content.IntentFilter;

import android.util.Log;

import com.spotify.android.appremote.api.ConnectionParams;
import com.spotify.android.appremote.api.Connector;
import com.spotify.android.appremote.api.SpotifyAppRemote;

import com.spotify.protocol.client.Subscription;
import com.spotify.protocol.types.PlayerState;
import com.spotify.protocol.types.Track;

public class MainActivity extends UnityPlayerActivity 
{
    public static MainActivity instance; // For Unity C# to trigger functions here
    public static String currentPlaying = ""; // For Unity C# to read current playing info
    
    private static final String CLIENT_ID = "your client id"; // Use your own Client Id
    private static final String REDIRECT_URI = "http://localhost:5000/callback"; // Also match this on the app settings page
    private SpotifyAppRemote mSpotifyAppRemote;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        instance = this;
    }
    
    // Triggered by Unity C# script
    public void PlaySong(String trackId) 
    {
        mSpotifyAppRemote.getPlayerApi().play("spotify:track:" + trackId);
    }

    @Override
    protected void onStart() 
    {
        super.onStart();
        ConnectionParams connectionParams =
                new ConnectionParams.Builder(CLIENT_ID)
                        .setRedirectUri(REDIRECT_URI)
                        .showAuthView(true)
                        .build();

        SpotifyAppRemote.connect(this, connectionParams, new Connector.ConnectionListener() 
        {
            public void onConnected(SpotifyAppRemote spotifyAppRemote) 
            {
                mSpotifyAppRemote = spotifyAppRemote;
                Log.d("MainActivity", "Connected! Yay!");

                // Now you can start interacting with App Remote
                connected();

            }

            public void onFailure(Throwable throwable) {
                Log.e("MyActivity", throwable.getMessage(), throwable);

                // Something went wrong when attempting to connect! Handle errors here
            }
        });
    }

    @Override
    protected void onStop() 
    {
        super.onStop();
        SpotifyAppRemote.disconnect(mSpotifyAppRemote);
    }

    private void connected() 
    {
        // Play a playlist
        mSpotifyAppRemote.getPlayerApi().play("spotify:playlist:37i9dQZF1DX2sUQwD7tbmL");

        // Subscribe to PlayerState
        mSpotifyAppRemote.getPlayerApi()
                .subscribeToPlayerState()
                .setEventCallback(playerState -> 
                {
                    final Track track = playerState.track;
                    if (track != null) {
                        Log.d("MainActivity", track.name + " by " + track.artist.name);
                        currentPlaying = track.name + " by " + track.artist.name;
                    }
                });
    }
}

From and to Unity C# script and Java

This part is straight-forward, just use AndroidJavaClass and AndroidJavaObject API.
With the above [Code for MainActivity.java] code, you can have a C# script to read the Spotify info and trigger to play a song.

Code for ExampleScript.cs

using System;
using UnityEngine;
using UnityEngine.UI;

public class ExampleScript : MonoBehaviour
{
    private AndroidJavaClass mainActivityClass;
    private AndroidJavaObject mainActivityObject;
    
    public Text currentPlayingText;

    void Start()
    {
        mainActivityClass = new AndroidJavaClass("com.unity3d.player.MainActivity");
        mainActivityObject = mainActivityClass.GetStatic<AndroidJavaObject>("instance");
    }
    
    private void Update()
    {
        UpdateCurrentPlaying();
    }

    public void PlaySong()
    {
        mainActivityObject.Call("PlaySong","4SFknyjLcyTLJFPKD2m96o"); // BLACKPINK - How You Like That
    }

    public void UpdateCurrentPlaying()
    {
        currentPlayingText.text = mainActivityClass.GetStatic<string>("currentPlaying");
    }
}

Spotify Android Media Notifications

Actually, you can get the current playing track info without the SDK! You can get:
track id, artist, album, track names and length, as well as playing status and position.
See https://developer.spotify.com/documentation/android/tutorials/android-media-notifications

⭐On your Android device, open Spotify app, click on your profile > Settings and privacy > Playback > enable Device Broadcast Status⭐

  1. In Assets/Plugins/Android folder, create a file called MyBroadcastReceiver.java, paste the below [Code for MyBroadcastReceiver.java] code to it.

Code for MyBroadcastReceiver.java
(The original code comes from: Spotify Android SDK documentation)

package com.unity3d.player;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    static final class BroadcastTypes 
    {
        static final String SPOTIFY_PACKAGE = "com.spotify.music";
        static final String PLAYBACK_STATE_CHANGED = SPOTIFY_PACKAGE + ".playbackstatechanged";
        static final String QUEUE_CHANGED = SPOTIFY_PACKAGE + ".queuechanged";
        static final String METADATA_CHANGED = SPOTIFY_PACKAGE + ".metadatachanged";
    }
    
    public static String currentPlaying = ""; // For Unity C# to read current playing info
    
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        long timeSentInMs = intent.getLongExtra("timeSent", 0L);

        String action = intent.getAction();

        if (action.equals(BroadcastTypes.METADATA_CHANGED)) 
        {
            String trackId = intent.getStringExtra("id");
            String artistName = intent.getStringExtra("artist");
            String albumName = intent.getStringExtra("album");
            String trackName = intent.getStringExtra("track");
            int trackLengthInSec = intent.getIntExtra("length", 0);
            // Do something with extracted information...
            currentPlaying = trackName + " by " + artistName;
        } 
        else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) 
        {
            boolean playing = intent.getBooleanExtra("playing", false);
            int positionInMs = intent.getIntExtra("playbackPosition", 0);
            // Do something with extracted information
        } 
        else if (action.equals(BroadcastTypes.QUEUE_CHANGED)) 
        {
            // Sent only as a notification, your app may want to respond accordingly.
        }
    }
}
  1. Open and edit the AndroidManifest.xml file again, add highlighted:
        <activity android:name=".MainActivity"
                ...bla bla bla...
        </activity>
        <receiver
                android:name=".MyBroadcastReceiver"
                android:enabled="true"
                android:exported="true">
            <intent-filter>
                <action android:name="com.spotify.music.playbackstatechanged"/>
                <action android:name="com.spotify.music.metadatachanged"/>
                <action android:name="com.spotify.music.queuechanged"/>
            </intent-filter>
        </receiver>
  1. Edit above [Code for MainActivity.java] code, in onCreate function, add highlighted:
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        instance = this;
        
        var receiver = new MyBroadcastReceiver();
        var filter1 = new IntentFilter("com.spotify.music.playbackstatechanged");
        var filter2 = new IntentFilter("com.spotify.music.metadatachanged");
        var filter3 = new IntentFilter("com.spotify.music.queuechanged");
        registerReceiver(receiver, filter1);
        registerReceiver(receiver, filter2);
        registerReceiver(receiver, filter3);
        Log.d("MainActivity", "Receiver Registered!");
    }
  1. Edit [Code for ExampleScript.cs] code to get whatever value from MyBroadcastReceiver.java πŸ™‚
  2. DONE! If you don’t need the SDK, I guess you know what to remove πŸ˜…

    If this helped you, please give this post a clap πŸ˜€ Thank you

    One thought on “Using Spotify Android SDK in Unity

    Leave a comment