解决Spotify Android SDK auth-lib的「需要明确用户授权」错误
Android Studio应用连接Spotify时授权失败问题
错误信息
{"message":"Explicit user authorization is required to use Spotify. The user has to complete the auth-flow to allow the app to use Spotify on their behalf"}
response.getError()返回内容:Authentication Service Error Unknown
已验证的配置
- Redirect URI设置为
com.example.loopify_5://callback,已在Spotify开发者后台正确配置,Client ID无误; - 已将正确的SHA密钥上传至开发者后台;
- 模拟器已安装Spotify,登录账号与开发者账号一致。
报错代码位置
报错发生在以下代码行:
AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(CLIENT_ID, AuthorizationResponse.Type.CODE, REDIRECT_URI);
完整代码
public class MainActivity extends AppCompatActivity { private static final String CLIENT_ID = "xxxx"; private static final String REDIRECT_URI = "com.example.loopify_5://callback"; private SpotifyAppRemote mSpotifyAppRemote; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); authenticateSpotify(); } private void authenticateSpotify() { AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(CLIENT_ID, AuthorizationResponse.Type.CODE, REDIRECT_URI); builder.setScopes(new String[]{"streaming"}); AuthorizationRequest request = builder.build(); AuthorizationClient.openLoginActivity(this, 1337, request); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); // Check if result comes from the correct activity if (requestCode == 1337) { AuthorizationResponse response = AuthorizationClient.getResponse(resultCode, intent); switch (response.getType()) { // Response was successful and contains auth token case TOKEN: Toast.makeText(MainActivity.this, "Here", Toast.LENGTH_SHORT).show(); connectToSpotifyRemote(); break; // Auth flow returned an error case ERROR: Toast.makeText(MainActivity.this, "Authorization error: " + response.getError() + response.getCode(), Toast.LENGTH_SHORT).show(); break; // Most likely auth flow was cancelled default: // Handle other cases } } } private void connectToSpotifyRemote() { 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!"); Toast.makeText(MainActivity.this, "Connected to Spotify Remote", Toast.LENGTH_SHORT).show(); // Now you can start interacting with App Remote connected(); } public void onFailure(Throwable throwable) { Toast.makeText(MainActivity.this, "Failed to connect to Spotify Remote", Toast.LENGTH_SHORT).show(); Log.e("MainActivity", throwable.getMessage(), throwable); // Something went wrong when attempting to connect! Handle errors here } }); } @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); } }); } }
解决方案
- 修复认证流程冲突
代码中onCreate调用authenticateSpotify()启动授权,同时onStart又直接触发SpotifyAppRemote.connect(),两次请求会导致认证逻辑混乱。移除onStart内的连接代码,仅保留授权成功后触发连接的逻辑:
@Override protected void onStart() { super.onStart(); // 移除原有SpotifyAppRemote.connect()调用 }
- 调整授权响应类型
将授权请求的类型从CODE改为TOKEN,适配Spotify App Remote的认证逻辑:
AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(CLIENT_ID, AuthorizationResponse.Type.TOKEN, REDIRECT_URI);
- 配置Manifest重定向规则
在AndroidManifest.xml的MainActivity中添加intent-filter,确保应用能接收重定向请求:
<activity android:name=".MainActivity"> <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="com.example.loopify_5" /> </intent-filter> </activity>
- 补充必要权限Scope
除streaming外,添加播放器操作所需的权限,确保应用有足够权限:
builder.setScopes(new String[]{"streaming", "user-read-playback-state", "user-modify-playback-state"});
- 清除Spotify缓存
在模拟器中进入Spotify应用设置,清除缓存和数据后重新登录,避免旧授权数据干扰。
内容的提问来源于stack exchange,提问作者NewCoder1423
相关产品推荐
相关产品推荐

