현재 진행하고 있는 리액트 네이티브 앱 개발 프로젝트에서 음악 스트리밍등 여러가지 기능을 구현하기 위해 Spotify를 연동하는 것은 핵심 과제 중 하나였다. 기존에 RN이 아닌 Java로 개발할 당시에는 spotify developer 공식문서를 포함하여 참고할 레퍼런스가 많았기에 어려움 없이 진행되었다.

하지만 RN에서 원격으로 spotify를 컨트롤 할 수 있는 방법은 검색 결과 react-native-spotify-remote 라이브러리를 사용하는 것이 유일했다. react-native-spotify-remote 라이브러리를 사용하는 과정에서 다양한 잇슈에 직면했고 꽤 많은 시간이 소요 됐기에 이 과정을 기록하고자 한다

 

1.spotify developer 앱 생성

https://developer.spotify.com/

 

Home | Spotify for Developers

Music, meet code. Powerful APIs, SDKs and widgets for simple and advanced applications.

developer.spotify.com

spotify developer 홈페이지에서 DASHBOARD로 이동 후 원하는 대로 App name 과 App description 작성하여 프로젝트를 생성해준다.

 

생성해준 프로젝트에 들어간 후 edit settings에서 redirect URI와 RN 페키지 명, sha1 값을 입력한다.

본인의 경우 이 sha1키를 잘못 등록해서 AUTHENTICATION_SERVICE UNAVAILABLE 에러가 발생했고 sha1 key 값이 문제였다는걸 알아차리고 해결하기 까지 굉장히 많은 시간을 낭비했다.

sha1 key값이 노트북 장치에 종속되는 값으로 알고 있었는데 프로젝트마다 다른 sha key값을 가지고 있었고 결과적으로 다른 안드로이드 프로젝트의 sha1 값을 등록해 주어 문제가 발생했었다.

 

보통 sha1 값을 뽑아내는 방법으로

keytool -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore

위와 같은 명령어를 사용하라는 글을 많이 볼 수 있을 것이다.

본인 RN프로젝트의 sha1 값을 생성하기 위해서는 debug.keystore 경로를 본인 RN 프로젝트의 경로로 바꿔주어야 한다.

보통 RN프로젝트를 생성하면 android/app경로에 debug.keystore 파일이 존재한다. 따라서 명령어를 프로젝트 경로에 맞게 아래와 같이 바꿔준다.

keytool -list -v -alias androiddebugkey -keystore C:\RNProject\Ssimille\client\android\app\debug.keystore

 

 

 

2.react-native-spotify-remote 사용하기

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

2-1)라이브러리 설치

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

위 링크 공식문서에서는

AndroidManifest.xml에 <queries> <package android:name="com.spotify.music" /> </queries>

를 추가해주라고 안내해주는데 본인의 경우 추가해주지 않아도 필요한 기능을 구현하는데 문제가 없었다.

 

3.test build

import React from 'react';
import {Text} from 'react-native';
import {
  auth as SpotifyAuth,
  remote as SpotifyRemote,
  ApiScope,
} from 'react-native-spotify-remote';

const spotifyConfig = {
  clientID: 'Your spotify developer client ID',
  redirectURL: 'http://ssimille.com/callback/',
  tokenRefreshURL: 'http://ssimille.com/callback/',
  tokenSwapURL: 'http://ssimille.com/callback/',
  scopes: [ApiScope.AppRemoteControlScope, ApiScope.UserFollowReadScope],
};

const Notice = () => {
  const spotify = async() => {
    try {
      const session = await SpotifyAuth.authorize(spotifyConfig);
      console.log(session);
      await SpotifyRemote.connect(session.accessToken);
      await SpotifyRemote.playUri('spotify:track:6IA8E2Q5ttcpbuahIejO74');
      
    } catch (err) {
      console.error("Couldn't authorize with or connect to Spotify", err);
    }
  }
  spotify()
  return <Text>Notice</Text>;
};
export default Notice;

본인의 경우 Typescript를 사용하지 않아 spotifyConfig 부분만 수정해 주었다.

 

4.Plugin with id 'maven' not found build 에러

해당 에러는 Gradle version 7.x 부터는 maven을 지원하지 않아서 발생하는 잇슈였다.

Solution 1) Gradle version 6.x 로 낮추기

Solution 2) maven-publish 사용하기

본인의 경우 에러가 발생한 line 23, 46 지점으로 이동 후 플러그인을 maven-publish로 수정해주었다.

5.Project with path ':react-native-events' could not be found in project ':react-native-spotify-remote'. build 에러

Solution) react-native-events 설치

npm install react-native-events --force (peer dependency 문제로 --force 옵션으로 우회 설치)

본인의 경우 최신 버젼(0.67.4)의 react-native를 사용해서 그런지

1)react-native link react-native-events 명령어로 따로 link 작업을 해주거나

2)https://github.com/cjam/react-native-spotify-remote 에 수동 link해주는 작업을 따로 해주지 않아도 더이상의 잇슈가 발생하지 않았음.

혹시 react-native-events link관련 잇슈 발생시 1), 2) 방법을 시도해 볼 것.

 

6.Configuration with name 'compile' not found. 에러

task androidJavadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += files(android.bootClasspath)
        classpath += files(project.getConfigurations().getByName('compile').asList())
        include '**/*.java'
    }

gradle 7 부터 compile configurations을 지원하지 않기 때문에 오류가 발생했다.

해결 방법으로 compile 대신 implementation이나 api 등을 사용하는 방법도 있지만 canBeResolved를 true로 설정하라는 추가 이슈가 발생함에 따라 다음에 방법으로 해결했다.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "33.0.0"
        minSdkVersion = 21
        compileSdkVersion = 33
        targetSdkVersion = 33

        // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
        ndkVersion = "23.1.7779620"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle")
        classpath("com.facebook.react:react-native-gradle-plugin")
    }
}

subprojects { subproject ->
    if (project['name'] == 'react-native-spotify-remote') {
        project.configurations { compile {} }
    }
}

android/build.gradle 파일에 subprojects 부분을 추가해주어 에러를 해결했다.

 

7.Could not set unknown property 'classifier' for task ':react-native-spotify-remote:androidJavadocJar' of type org.gradle.api.tasks.bundling.Jar. 에러

task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
        classifier = 'javadoc'
        from androidJavadoc.destinationDir
    }

task androidSourcesJar(type: Jar) {
    classifier = 'sources'
    from android.sourceSets.main.java.srcDirs
    include '**/*.java'
}

위 부분에서 classifier property를 읽지 못하며 에러가 발생했고 검색 결과 아래와 같이 수정해주었다.

task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
    archiveClassifier = 'javadoc'
    from androidJavadoc.destinationDir
}

task androidSourcesJar(type: Jar) {
    archiveClassifier = 'sources'
    from android.sourceSets.main.java.srcDirs
    include '**/*.java'
}

8.Could not create task ':react-native-events:compileDebugJavaWithJavac' 에러

node_modules/react-native-events/android/build.gradle 파일에서 compileSdkVersion을 올려주어 해결했다.

android {
    compileSdkVersion 30 // 26 -> 30
    buildToolsVersion '28.0.3'

    defaultConfig {
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }
    lintOptions {
        abortOnError false
    }
}

 

9.Could not find method mavenDeployer() build 에러

task installArchives(type: Upload) {
        configuration = configurations.archives
        repositories.mavenDeployer {
            // Deploy to react-native-event-bridge/maven, ready to publish to npm
            repository url: "file://${projectDir}/../android/maven"
            configureReactNativePom pom
        }
    }

Maven repository 저장소를 지정하는 업로드 아카이브 task에서 문제가 발생한 것으로 보이는데 mavenDeployer()함수를 호출하지 못하는 것 같았다.

Maven publish 관련 공식 문서를 읽어본 결과 task installArchives(type: Upload) 코드블럭 전체를 지우고 해당 작업을 위한 코드를 아래와 같이 수정하여 해결해 주었다.

 

publishing {
        repositories {
            maven {
                url = "file://${projectDir}/../android/maven"
            }
        }
    }

 

10.patch-package로 라이브러리 수정사항 유지(7/18 추가)

프로젝트를 새로 clone하거나 프로젝트에 npm install을 다시 해주게 될 경우 수정하기 전 기존 라이브러리로 다시 받아오게 되고 위에 수정작업을 다시 해주어야했다.  때문에 patch-package를 수정사항을 기록하여 라이브러리 변경사항이 적용될 수 있도록 하였다.

yarn patch-package react-native-spotify-remote

 

11.Build success 및 example code 실행 결과

성공적으로 빌드가 되어 Spotify Auth를 위한 로그인창이 나타나며 본인의 경우 Google 계정으로 스포티파이 계정을 생성했기 때문에 CONTINUE WITH GOOGLE로 진행하였다. 또한 위에 사진은 실제 기기에서는 스포티파이 정책에 의해 화면 캡쳐가 불가능해 에뮬레이터로 실행한 결과 화면으로 실제 기기에서의 실행 화면과 약간의 차이가 있다. 

 

정상적으로 로그인이 진행되면 스포티파이 앱에서

await SpotifyRemote.playUri('spotify:track:6IA8E2Q5ttcpbuahIejO74');

해당 트랙을 재생하는 것을 확인할 수 있었다.