Spotify is one of the world’s most popular music streaming platforms, and it has a vast collection of songs, albums, playlists, and podcasts. With the Spotify Web API, developers can create amazing applications that interact with the Spotify service. Using the Web API’s endpoints, one can get detailed metadata about artists, albums, and tracks directly from the Spotify Data Catalogue. It also provides access to the currently logged-in user’s data, such as the playlists and tracks saved in the Your Music Library of the user.
In this article, we will create an Android app using which we can create a new playlist in the logged-in user’s Spotify Account. Basics of Java and Android App Development knowledge are prerequisites for this article. We will also use the Volley library to make the networking calls to the Spotify Web API and the GSON library to parse the returned JSON data.
Step By Step Implementation
Step 1: Create a New Project in Android Studio
Please refer to How to Create/Start a New Project in Android Studio to learn how to create a new project. Name the project “My Spotify App” (or any name of your choice) and select Java as the programming language. A new project will be created with a Main Activity and its XML file as follows:
Step 2: Create an app in the Spotify Dashboard
- Head over to the Spotify Dashboard and log in using your Spotify account.
- Click on “Create an app.”
- Write the app name (My Spotify App), give it a description, accept the T&C, and click on create button.
Once the app is created, the Dashboard will look like this:
Step 3: Finalize project settings in the dashboard
We will add a Redirect URI, our package name, and the SHA-1 key of our Android Studio. The Redirect URI is used to redirect back to your application from a web browser (in this case, the web page for authentication). Therefore we create a unique URI for our app.
The package name of an Android app is a unique identifier that distinguishes it from other apps on the device and the Google Play store. Similarly, the SHA-1 key is used to uniquely identify your Android Studio installed on your PC. Refer to this article to learn how to get the SHA-1 key in Android Studio.
These details are needed to restrict our API key to only work with our app and prevent unauthorized use by others. Follow the following steps to add these details:
- In the project dashboard, click on “Edit Settings.”
- Under “Redirect URIs”, add your package name as a redirect URI: <package-name>://callback, which in this case is:
com.example.myspotifyapp://callback
- Also, add your package name under the “Android Packages” section, along with your Android Studio’s unique SHA-1 key.
Click on Save, and you will be done with the project settings in the Spotify Dashboard. Your app will currently be in development mode and will only support a maximum of 25 users. To make your app accessible to more than 25 users, you will need to Submit a quota extension request to the Spotify team.
Step 4: Add the necessary dependencies and permissions
We will need to authenticate the user to make calls to the Spotify Web API. We will use the Spotify Android auth library, which is responsible for authenticating the user and fetching the authorization code/access token that can subsequently be used to play music or in requests to the API.
We will use the Volley library to make HTTP calls to the API and the GSON library to parse the results and use them in our app. We’ll check the Maven Central repository to get the latest version of the libraries. The links for each library are mentioned below. Choose the latest version and Gradle from the respective dropdowns, copy the dependency and, paste it into your module-level gradle file, then sync your project.
The Maven Central repository will look as follows:
Since Spotify Auth library version 2.0.0, we must also provide the scheme and host of the redirect URI our app uses for authorizing in our module-level build.gradle file. In this case, we need to paste the following in our defaultConfig scope within android:
manifestPlaceholders = [redirectSchemeName: "com.example.myspotifyapp", redirectHostName: "callback"]
Sync your project. The Gradle file will look like this:
We must also add internet permission in our app’s manifest file. Paste the following snippet in your AndroidManifest.xml file above the application tag:
<uses-permission android:name="android.permission.INTERNET" />
Step 5: Add the necessary string values in the strings.xml file
Adding the strings like keys etc. which are used in many places across the android app in the strings.xml file, is considered a best practice. We’ll store our Client ID, Redirect URI, and the shared preferences key in the string.xml file. You can get your Client ID and redirect URI from the Spotify Developer Dashboard. We’ll use “Spotify” as our key to access shared preferences. The code for the strings.xml file will look as follows:
XML
< resources >
< string name = "app_name" >My Spotify App</ string >
< string name = "CLIENT_ID" >YOUR_CLIENT_ID</ string >
< string name = "REDIRECT_URI" >YOUR_REDIRECT_URI</ string >
< string name = "shared_pref_key" >Spotify</ string >
</ resources >
|
Step 6: Add the code for authentication
Create a new Activity, name it LoginActivity in Android Studio, and select it as the launcher activity. We will write the code for authentication in this activity and launch the MainActivity once authentication is successful. Once authentication is done, we receive a token, which is later used for authorization in making requests to the API. We’ll store the token in android’s persistent storage Shared Preferences for later use. We also need to define the scope to access the specific information we’ll be accessing from our user’s account. For example, the user-read-email scope is used to read the linked email address of the user. You can read more about scopes here. The code for LoginActivity.java is as shown below:
Java
package com.example.myspotifyapp;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.spotify.sdk.android.auth.AuthorizationClient;
import com.spotify.sdk.android.auth.AuthorizationRequest;
import com.spotify.sdk.android.auth.AuthorizationResponse;
public class LoginActivity extends AppCompatActivity {
private SharedPreferences.Editor editor;
private SharedPreferences sharedPreferences;
private RequestQueue requestQueue;
private static final int REQUEST_CODE = 1234 ;
private static final String SCOPES
= "user-read-email,user-read-private,playlist-modify-private,playlist-modify-public" ;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
sharedPreferences = this .getSharedPreferences(
getString(R.string.shared_pref_key),
MODE_PRIVATE);
requestQueue = Volley.newRequestQueue( this );
AuthorizationRequest.Builder builder
= new AuthorizationRequest.Builder(
getString(R.string.CLIENT_ID),
AuthorizationResponse.Type.TOKEN,
getString(R.string.REDIRECT_URI));
builder.setScopes( new String[] { SCOPES });
AuthorizationRequest request = builder.build();
AuthorizationClient.openLoginActivity(
this , REQUEST_CODE, request);
}
protected void onActivityResult( int requestCode,
int resultCode,
Intent intent)
{
super .onActivityResult(requestCode, resultCode,
intent);
if (requestCode == REQUEST_CODE) {
AuthorizationResponse response
= AuthorizationClient.getResponse(
resultCode, intent);
switch (response.getType()) {
case TOKEN:
editor = getSharedPreferences(
getString(
R.string.shared_pref_key),
MODE_PRIVATE)
.edit();
editor.putString( "token" ,
response.getAccessToken());
editor.apply();
Toast.makeText( this , "Auth successful" ,Toast.LENGTH_SHORT)
.show();
startActivity( new Intent(LoginActivity. this ,
MainActivity. class ));
break ;
case ERROR:
Log.d( "LoginActivity" , response.getError());
break ;
default :
Log.d( "LoginActivity" , response.toString());
}
}
}
}
|
The XML file of LoginActivity, MainActivity, and its Java file will be the same as the default for now. You can now run the app and check if auth is running successfully. You should see a toast saying “Auth successful”, and the MainActivity should pop up right after.
Step 7: Create helper classes to get logged-in user’s details
Now that the authentication is done, we will try to get some user details and view them in the MainActivity. We need to get the user details so that we can get hold of the user’s Spotify ID, which will be needed to create a playlist in that user’s account and much more stuff. You can read more about the endpoint for getting user details here. We will first need to create a model User class to serialize the response from the endpoint. We will create variables for name, email, and user ID because that is the only information we currently need.
Java
public class User {
public String display_name;
public String email;
public String id;
public String getDisplayName() {
return display_name;
}
public String getEmail() {
return email;
}
public String getId() {
return id;
}
}
|
We will now create a UserInfo class to fetch the response from the API’s endpoint. We will make the call to the API using the Volley library and parse it into the User class using GSON.
Java
import android.content.SharedPreferences;
import com.android.volley.AuthFailureError;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
public class UserInfo
{
private SharedPreferences sharedPreferences;
private RequestQueue queue;
private User user;
public UserInfo(RequestQueue queue, SharedPreferences sharedPreferences) {
this .queue = queue;
this .sharedPreferences = sharedPreferences;
}
public User getUser() {
return user;
}
public void get( final VolleyCallBack callBack) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(URL,
null , response ->
{
Gson gson = new Gson();
user = gson.fromJson(response.toString(), User. class );
callBack.onSuccess();
}, error -> get(() -> {
})) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String token = sharedPreferences.getString( "token" , "" );
String auth = "Bearer " + token;
headers.put( "Authorization" , auth);
return headers;
}
};
queue.add(jsonObjectRequest);
}
}
|
Step 8: Display the details in the Main Activity
Add a TextView on which we will display the user’s details. The XML code for the Main Activity class is given below:
XML
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
< TextView
android:id = "@+id/userDetails"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "30dp"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
</ androidx.constraintlayout.widget.ConstraintLayout >
|
Now we will write the code in the MainActivity.java file to display the user’s data.
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView userDetails;
SharedPreferences sharedPreferences;
private static final String TAG = "MainActivity" ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userDetails = findViewById(R.id.userDetails);
sharedPreferences = this .getSharedPreferences(getString(R.string.shared_pref_key),
MODE_PRIVATE);
String name = sharedPreferences.getString( "display_name" , "Couldn't retrieve name" );
String email = sharedPreferences.getString( "email" , "Couldn't get token" );
userDetails.setText( "Name: " +name);
userDetails.append( "\nEmail ID: " +email);
}
}
|
You can now run the app. You will be able to see your name and email on the Main Activity. A sample screenshot is attached below:
Step 9: Add code to create a new playlist in your Spotify account
We will now programmatically create a playlist in our Spotify account. The details of the API for creating a new playlist can be found here. First, we will create a button in the Main Activity for creating a new playlist. The XML code is as follows:
XML
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
< Button
android:id = "@+id/createPlaylistBtn"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_margin = "30dp"
android:text = "Create New Playlist"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent" />
< TextView
android:id = "@+id/userDetails"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "30dp"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
</ androidx.constraintlayout.widget.ConstraintLayout >
|
Now we will make the request to the endpoint on the button click in our Main Activity. The Java code is as follows:
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
TextView userDetails;
Button createPlaylistBtn;
SharedPreferences sharedPreferences;
private RequestQueue queue;
private static final String TAG = "MainActivity" ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userDetails = findViewById(R.id.userDetails);
createPlaylistBtn = findViewById(R.id.createPlaylistBtn);
sharedPreferences = this .getSharedPreferences(getString(R.string.shared_pref_key),
MODE_PRIVATE);
String name = sharedPreferences.getString( "display_name" , "Couldn't retrieve name" );
String email = sharedPreferences.getString( "email" , "Couldn't get token" );
userDetails.setText( "Name: " +name);
userDetails.append( "\nEmail ID: " +email);
queue = Volley.newRequestQueue( this );
createPlaylistBtn.setOnClickListener(view -> {
createTestPlaylist();
});
}
private void createTestPlaylist()
{
JSONObject data = new JSONObject();
try {
data.put( "name" , "The Empty Canvas" );
data.put( "description" , "A playlist created by me using Spotify's Web API :)" );
} catch (JSONException e) {
throw new RuntimeException(e);
}
+ sharedPreferences.getString( "userId" , "Couldn't get userid" ) + "/playlists" ;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, endpoint,
data, response -> {
Toast.makeText( this , "\"The Empty Canvas\" playlist created" , Toast.LENGTH_SHORT).show();
},
error -> {
Toast.makeText( this , error.toString(), Toast.LENGTH_SHORT).show();
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String token = sharedPreferences.getString( "token" , "" );
String auth = "Bearer " + token;
headers.put( "Authorization" , auth);
headers.put( "Content-Type" , "application/json" );
return headers;
}
};
queue.add(jsonObjectRequest);
}
}
|
You can now run the app, and after clicking the button, you’ll find a playlist has been created in your Spotify account. A sample app and Spotify screenshots have been attached below.
Share your thoughts in the comments
Please Login to comment...