Intereting Posts
Использование функции по умолчанию для интерфейса в Kotlin Отправка SMS с помощью Twilio и Android только один сопутствующий объект разрешен для каждого класса в Котлине Котлин: Почему? оператор генерирует нулевые проверки при компиляции для jvm? Проводка в пользовательский интерфейс Что представляет собой массивOfNulls в Котлине? оба приложения: showAsAction = "ifRoom" и андроид: showAsAction = "ifRoom" работают не так, как ожидалось Как использовать делегаты разрешения библиотеки поддержки Android? Альтернатива классу Math для поплавков статический эквивалент в Android для kotlin, чтобы избежать утечек памяти обработчика Можно ли передать ссылку на i-й элемент примитивного массива? Kotlin: передать массив методу varargs с оператором распространения Нулевая проверка, если условия Не выходите из программы Kotlin, пока выполняется несколько сопрограмм Равномерное авторазведение нескольких текстовых элементов

Авторизация Spotify Code отклоняется за плохие учетные данные, несмотря на то, что отправлен действительный токен

У меня возникли проблемы с тем, чтобы поток клиентских кодов Spotify работал на Android. Сначала я использовал поток учетных данных клиента, но ключи, предоставленные с помощью этого подхода, истекают через час. При этом мне удалось заставить поток учетных данных работать. После перехода на поток клиентского кода я могу получить обратный код доступа, который является согласованным по форме с теми, которые я получил через поток учетных данных, но они отклоняются при попытке активировать объект потоковой передачи с помощью ошибки kSpErrorLoginBadCredentials.

Я проверяю подлинность на удаленном сервере с устройства. Код помечен ниже на основе устройств, на которых он выполняется.

S – Сервер (удаленный)

H – Хост (локальный)


H – SpotifyUtils.kt

fun loginToSpotify(fragment: Fragment) { val request = AuthenticationRequest.Builder(fragment.getString(R.string.spotify_key), AuthenticationResponse.Type.TOKEN, "nextup://callback") .setScopes(arrayOf("streaming", "playlist-read-private", "playlist-read-collaborative")) .build() fragment.startActivityForResult(AuthenticationClient.createLoginActivityIntent(fragment.activity, request), REQUEST_CODE) } 

H – HostSetupFragment.java

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE: SpotifyUtils.INSTANCE.processLoginResponse(getContext(), resultCode, data, new Callable<Void>() { @Override public Void call() throws Exception { ... } }); break; } } 

H – SpotifyUtils.kt

 fun processLoginResponse(c: Context, resultCode: Int, data: Intent, callable: Callable<*>) { val response = AuthenticationClient.getResponse(resultCode, data) when (response.type) { AuthenticationResponse.Type.CODE -> task { val client = OkHttpClient() val request = Request.Builder() .url("http://{{ip}}:{{port}}/spotifyAuth/initial") .header("code", response.code) .build() client.newCall(request).execute() } successUi { response -> val responses = response.body()?.string()?.split(":") val editor = Utils.getPrefs(c).edit() info("access" + responses!![0]) editor.putString("spotifyAccess", responses!![0]) editor.putString("spotifyRefresh", responses[1]) editor.putLong("spotifyLastFetched", System.currentTimeMillis()) editor.apply() callable.call() } fail { exception -> error(exception) } // Auth flow returned an error AuthenticationResponse.Type.ERROR -> Log.d("", "Auth error: " + response.error) // Most likely auth flow was cancelled else -> Log.d("", "Auth result: " + response.type) }// Response was successful and contains auth token } 

S – SpotifyAuth.java

 @Path("/spotifyAuth") public class SpotifyAuth { // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media type "text/plain" @Produces("text/json") @Path("/initial") public String getAuth(@HeaderParam("code") String code) { if(code == null) { return "null"; } final Api api = Api.builder() .clientId("...") .clientSecret("...") .redirectURI("nextup://callback") .build(); try { final AuthorizationCodeCredentials creds = api.authorizationCodeGrant(code).build().get(); return creds.getAccessToken() + ":" + creds.getRefreshToken(); } catch (IOException e) { e.printStackTrace(); } catch (WebApiException e) { e.printStackTrace(); } return null; } // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media type "text/plain" @Produces("text/json") @Path("/refresh") public String getRefreshedAuth(@HeaderParam("code") String code) { if(code == null) { return "null"; } final Api api = Api.builder() .clientId("...") .clientSecret("...") .refreshToken(code) .build(); try { final RefreshAccessTokenCredentials creds = api.refreshAccessToken().build().get(); return creds.getAccessToken(); } catch (IOException e) { e.printStackTrace(); } catch (WebApiException e) { e.printStackTrace(); } return null; } 

H – HostActivity.java

  SpotifyUtils.INSTANCE.getFreshAccessToken(this, new Function1<String, Unit>() { @Override public Unit invoke(String s) { System.out.println("token is " + s); getSpotifyPlayer(new Config(HostActivity.this, s, getString(R.string.spotify_key))); return Unit.INSTANCE; } });