react-native-spotify-remote

repository·master·Indexed 42 days ago

https://github.com/cjam/react-native-spotify-remote

A React Native wrapper around the Spotify Remote SDKs for iOS and Android (version 1.0.0-1). It provides a bridge to control Spotify playback and manage authentication, including support for token swapping and refreshing via an external server.

Tokens
7.8K
Snippets
26
Records
29
Agent score
55%

What's inside react-native-spotify-remote

  1. Configure Android linking and Auth Callback

    master

    If autolinking fails on Android, follow these manual steps:

    1. Manual Linking

    • MainApplication.java: Add import com.reactlibrary.RNSpotifyRemotePackage; and add packages.add(new RNSpotifyRemotePackage()); to the getPackages() method.
    • settings.gradle: Append:
      include ':react-native-spotify-remote'
      project(':react-native-spotify-remote').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-spotify-remote/android')
    • app/build.gradle: Add implementation project(':react-native-spotify-remote') to the dependencies block.

    2. Auth Callback Configuration

    In android/app/src/main/AndroidManifest.xml, add the following activities inside the <application> tag:

    <activity
        android:exported="true"
        android:name="com.spotify.sdk.android.authentication.AuthCallbackActivity"
        android:theme="@android:style/Theme.Translucent.NoTitleBar">
    
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
    
            <data
                android:scheme="<YOUR_APPLICATION_SCHEME>"
                android:host="<YOUR_APPLICATION_CALLBACK>"/>
        </intent-filter>
    </activity>
    
    <activity
        android:name="com.spotify.sdk.android.authentication.LoginActivity"
        android:theme="@android:style/Theme.Translucent.NoTitleBar">
    </activity>

    Note: Replace <YOUR_APPLICATION_SCHEME> and <YOUR_APPLICATION_CALLBACK> with your actual Spotify app credentials.

  2. Setup the Example Token Refresh Server

    master

    The example-server is a utility used to swap and refresh Spotify API tokens. To set it up:

    1. Install dependencies:
      yarn
      # or
      npm install
    2. Create a .env file in the root directory with your Spotify credentials and encryption settings.
    3. Start the server:
      yarn start
      Alternatively, you can specify a PORT via the command line when starting the server with node.
    yarn
    # or
    npm install
    
    yarn start
  3. Configure environment variables for the example app

    master

    The example app uses react-native-dotenv. Create a .env file in the example/ root directory with the following keys.

    Note: If environment variable changes are not reflected, restart the packager using yarn start --reset-cache.

    • SPOTIFY_CLIENT_ID: Your client ID from the Spotify Dashboard.
    • SPOTIFY_REDIRECT_URL: The redirect URI registered in your Spotify Dashboard. This must also be configured in your app's Info.plist per the Spotify iOS Quickstart guide.
    • SPOTIFY_TOKEN_REFRESH_URL: The endpoint for token refreshing (e.g., http://{MACHINE_IP_ADDRESS}:3000/refresh).
    • SPOTIFY_TOKEN_SWAP_URL: The endpoint for token swapping (e.g., http://{MACHINE_IP_ADDRESS}:3000/swap).

    To use the default endpoints, you must run the Example Server.

    SPOTIFY_CLIENT_ID="client_id_from_spotify_dashboard"
    SPOTIFY_REDIRECT_URL="redirect_uri_registered_in_spotify_dashboard"
    SPOTIFY_TOKEN_REFRESH_URL="http://{MACHINE_IP_ADDRESS}:3000/refresh"
    SPOTIFY_TOKEN_SWAP_URL="http://{MACHINE_IP_ADDRESS}:3000/swap"
  4. Configure iOS Auth Callback

    master

    To handle the callback from the Spotify app on iOS, modify your AppDelegate.m to include the RNSpotifyRemoteAuth handler:

    #import "AppDelegate.h"
    
    #import <React/RCTBundleURLProvider.h>
    #import <React/RCTRootView.h>
    #import <RNSpotifyRemote.h>
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
    {
      return [[RNSpotifyRemoteAuth sharedInstance] application:application openURL:URL options:options];
    }
    
    @end
  5. Configure iOS linking and Cocoapods

    master

    For React Native versions > 0.61, auto-linking should work. If you need to manually configure iOS:

    Add the following line to your ios/Podfile within your project target:

    pod 'RNSpotifyRemote', :path => '../node_modules/react-native-spotify-remote'

    Manual Linking

    If you do not use Cocoapods:

    1. Add the frameworks from node_modules/react-native-spotify-remote/ios/external/SpotifySDK to Linked Frameworks and Libraries in your XCode project settings.
    2. Add ../node_modules/react-native-spotify-remote/ios/external/SpotifySDK to Framework Search Paths in your project settings.

    Note: This library requires XCode 11 or newer.

    Troubleshooting: If you encounter 'React/RCTConvert.h' file not found, try adding React as an explicit dependency of the RNSpotifyRemote target in XCode.

  6. Set up the React Native Spotify Remote Example Project

    master

    To run the example project, you must first install the dependencies, install iOS pods, and build the library itself to generate the required dist folder.

    1. Run yarn install in the example directory.
    2. Install Pods: cd ios && pod install && cd ..
    3. Build the library: Navigate to the root directory and run yarn install && yarn build to generate the library's dist folder.
    # 1. Install dependencies
    yarn install
    
    # 2. Install Pods
    cd ios && pod install && cd ..
    
    # 3. Build the library (from the root directory)
    cd ..
    yarn install && yarn build
  7. Install react-native-spotify-remote

    master

    Install the library using yarn or npm:

    yarn add react-native-spotify-remote

    or

    npm install --save react-native-spotify-remote

    Android 11 and Above Requirement: You must add the following <queries> block to your AndroidManifest.xml to allow the app to interact with the Spotify package:

    <queries>
      <package android:name="com.spotify.music" />
    </queries>
  8. Integrate the Token Refresh Server with react-native-spotify-remote

    master

    Once the server is running, configure your React Native application by setting the following URLs to point to your server's endpoints. Replace <SERVER_URL> with your server's address and <PORT> with the running port (default 3000):

    • tokenSwapURL: http://<SERVER_URL>:<PORT>/swap
    • tokenRefreshURL: http://<SERVER_URL>:<PORT>/refresh
    tokenSwapURL="http://<SERVER_URL>:<PORT>/swap"
    tokenRefreshURL="http://<SERVER_URL>:<PORT>/refresh"
  9. Configure environment variables for the Token Refresh Server

    master

    The server requires the following environment variables, which should be placed in a .env file. These values must be obtained from the Spotify Developer Dashboard.

    Required Variables:

    • SPOTIFY_CLIENT_ID: Your Spotify Client ID.
    • SPOTIFY_CLIENT_SECRET: Your Spotify Client Secret.
    • SPOTIFY_CLIENT_CALLBACK: The callback URL registered in your Spotify Dashboard.
    • ENCRYPTION_SECRET: A large, secure secret string used for encryption.
    • ENCRYPTION_METHOD: The encryption method (e.g., aes-256-ctr).

    Optional Variables:

    • PORT: The port the server runs on (defaults to 3000).
    SPOTIFY_CLIENT_ID="client_id_from_spotify_dashboard"
    SPOTIFY_CLIENT_SECRET="client_secret_from_spotify_dashboard"
    SPOTIFY_CLIENT_CALLBACK="callback_registered_in_spotify_dashboard"
    ENCRYPTION_SECRET="THISWILLBEABIGSECRET"
    ENCRYPTION_METHOD="aes-256-ctr"
  10. Use react-native-spotify-remote in TypeScript

    master

    To use the library, import auth and remote modules. You must provide an ApiConfig object containing your Spotify client credentials and redirect URLs.

    Note: An external server must be running to handle OAuth token swap and refresh calls.

    import {
      auth as SpotifyAuth,
      remote as SpotifyRemote,
      ApiScope,
      ApiConfig,
    } from "react-native-spotify-remote";
    
    const spotifyConfig: ApiConfig = {
      clientID: "SPOTIFY_CLIENT_ID",
      redirectURL: "SPOTIFY_REDIRECT_URL",
      tokenRefreshURL: "SPOTIFY_TOKEN_REFRESH_URL",
      tokenSwapURL: "SPOTIFY_TOKEN_SWAP_URL",
      scopes: [ApiScope.AppRemoteControlScope, ApiScope.UserFollowReadScope],
    };
    
    async function playEpicSong() {
      try {
        // 1. Authorize the user
        const session = await SpotifyAuth.authorize(spotifyConfig);
        
        // 2. Connect to the Spotify Remote
        await SpotifyRemote.connect(session.accessToken);
        
        // 3. Control playback
        await SpotifyRemote.playUri("spotify:track:6IA8E2Q5ttcpbuahIejO74");
        await SpotifyRemote.seek(58000);
      } catch (err) {
        console.error("Couldn't authorize with or connect to Spotify", err);
      }
    }
    import {
      auth as SpotifyAuth,
      remote as SpotifyRemote,
      ApiScope,
      ApiConfig,
    } from "react-native-spotify-remote";
    
    // Api Config object, replace with your own applications client id and urls
    const spotifyConfig: ApiConfig = {
      clientID: "SPOTIFY_CLIENT_ID",
      redirectURL: "SPOTIFY_REDIRECT_URL",
      tokenRefreshURL: "SPOTIFY_TOKEN_REFRESH_URL",
      tokenSwapURL: "SPOTIFY_TOKEN_SWAP_URL",
      scopes: [ApiScope.AppRemoteControlScope, ApiScope.UserFollowReadScope],
    };
    
    // Initialize the library and connect the Remote
    // then play an epic song
    async function playEpicSong() {
      try {
        const session = await SpotifyAuth.authorize(spotifyConfig);
        await SpotifyRemote.connect(session.accessToken);
        await SpotifyRemote.playUri("spotify:track:6IA8E2Q5ttcpbuahIejO74");
        await SpotifyRemote.seek(58000);
      } catch (err) {
        console.error("Couldn't authorize with or connect to Spotify", err);
      }
    }
  11. Configure Metro for the example project

    master

    The metro.config.js in the example directory is configured to handle peerDependencies correctly by preventing multiple versions of the same module from being loaded. It achieves this by blacklisting the peerDependencies located in the repository root and aliasing them to the versions installed within the example/node_modules folder using extraNodeModules.

    const path = require('path');
    const blacklist = require('metro-config/src/defaults/blacklist');
    const escape = require('escape-string-regexp');
    const pak = require('../package.json');
    
    const root = path.resolve(__dirname, '..');
    
    const modules = Object.keys({
      ...pak.peerDependencies,
    });
    
    module.exports = {
      projectRoot: __dirname,
      watchFolders: [root],
    
      // We need to make sure that only one version is loaded for peerDependencies
      // So we blacklist them at the root, and alias them to the versions in example's node_modules
      resolver: {
        blacklistRE: blacklist(
          modules.map(
            (m) =>
              new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
          )
        ),
    
        extraNodeModules: modules.reduce((acc, name) => {
          acc[name] = path.join(__dirname, 'node_modules', name);
          return acc;
        }, {}),
      },
    
      transformer: {
        getTransformOptions: async () => ({
          transform: {
            experimentalImportSupport: false,
            inlineRequires: true,
          },
        }),
      },
    };