Flutter:如何将原生 SDK(Spotify Android SDK)添加到应用程序中?
Posted
技术标签:
【中文标题】Flutter:如何将原生 SDK(Spotify Android SDK)添加到应用程序中?【英文标题】:Flutter: How to add a native SDK (Spotify Android SDK) to an app? 【发布时间】:2020-02-23 03:38:19 【问题描述】:我想编写一个访问 Spotify android SDK 的包。我正在尝试添加身份验证。那是行不通的。我没有设法打开登录屏幕。我是否需要在 dart 代码中添加一个视图(如此处所述:https://60devs.com/how-to-add-native-code-to-flutter-app-using-platform-views-android.html)?
飞镖:
...
void initPlatformState() async
try
String test = await Nativecode05.spotifyTest;
print(test);
on PlatformException
platformVersion = 'Failed';
...
包装:
import 'dart:async';
import 'package:flutter/services.dart';
class Nativecode05
static const MethodChannel _channel = const MethodChannel('nativecode05');
static Future<String> get spotifyTest async
final String version = await _channel.invokeMethod('spotifyTest');
return version;
包中的Java代码:
package example.com.nativecode05;
import io.flutter.Log;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import com.spotify.android.appremote.api.ConnectionParams;
import com.spotify.android.appremote.api.Connector;
import com.spotify.android.appremote.api.SpotifyAppRemote;
import static android.content.ContentValues.TAG;
/** Nativecode05Plugin */
public class Nativecode05Plugin implements MethodCallHandler
private static final String CLIENT_ID = "7b23dface41e4a9595276a7c12262143";
private static final String REDIRECT_URI = "http://cape/callback";
private SpotifyAppRemote mSpotifyAppRemote;
private Registrar mRegistrar;
/** Plugin registration. */
public static void registerWith(Registrar registrar)
final MethodChannel channel = new MethodChannel(registrar.messenger(), "nativecode05");
channel.setMethodCallHandler(new Nativecode05Plugin(registrar));
Nativecode05Plugin(Registrar registrar)
mRegistrar = registrar;
@Override
public void onMethodCall(MethodCall call, Result result)
if (call.method.equals("spotifyTest"))
result.success("test");
performAuthorization();
return;
result.notImplemented();
private void performAuthorization()
Log.d(TAG, "Performing authorization...");
// Set the connection parameters
ConnectionParams connectionParams =
new ConnectionParams.Builder(CLIENT_ID)
.setRedirectUri(REDIRECT_URI)
.showAuthView(true)
.build();
SpotifyAppRemote.connect(mRegistrar.activeContext(), connectionParams,
new Connector.ConnectionListener()
@Override
public void onConnected(SpotifyAppRemote spotifyAppRemote)
mSpotifyAppRemote = spotifyAppRemote;
Log.d(TAG, "Connected! Yay!");
// Now you can start interacting with App Remote
//connected();
@Override
public void onFailure(Throwable throwable)
Log.e(TAG, throwable.getMessage(), throwable);
// Something went wrong when attempting to connect! Handle errors here
);
终端中的结果:
Launching lib\main.dart on SM G960F in debug mode...
Initializing gradle...
Resolving dependencies...
Running Gradle task 'assembleDebug'...
Built build\app\outputs\apk\debug\app-debug.apk.
Installing build\app\outputs\apk\app.apk...
D/EmergencyMode(17067): [EmergencyManager] android createPackageContext successful
D/InputTransport(17067): Input channel constructed: fd=87
D/ViewRootImpl@a7a19f9[MainActivity](17067): setView = DecorView@97d1d3e[MainActivity] TM=true MM=false
W/ecode05_exampl(17067): Accessing hidden method Landroid/view/accessibility/AccessibilityNodeInfo;->getSourceNodeId()J (light greylist, reflection)
W/ecode05_exampl(17067): Accessing hidden method Landroid/view/accessibility/AccessibilityRecord;->getSourceNodeId()J (light greylist, reflection)
W/ecode05_exampl(17067): Accessing hidden field Landroid/view/accessibility/AccessibilityNodeInfo;->mChildNodeIds:Landroid/util/LongArray; (light greylist, reflection)
W/ecode05_exampl(17067): Accessing hidden method Landroid/util/LongArray;->get(I)J (light greylist, reflection)
D/SurfaceView(17067): onWindowVisibilityChanged(0) true 5395cb5 of ViewRootImpl@a7a19f9[MainActivity]
D/ViewRootImpl@a7a19f9[MainActivity](17067): dispatchAttachedToWindow
D/ViewRootImpl@a7a19f9[MainActivity](17067): Relayout returned: old=[0,0][1440,2960] new=[0,0][1440,2960] result=0x7 surface=valid=true 508548042752 changed=true
I/OpenGLRenderer(17067): Initialized EGL, version 1.4
D/OpenGLRenderer(17067): Swap behavior 2
D/mali_winsys(17067): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
D/OpenGLRenderer(17067): eglCreateWindowSurface = 0x765347ca00, 0x7667d35010
D/SurfaceView(17067): show() Surface(name=SurfaceView - example.com.nativecode05_example/example.com.nativecode05_example.MainActivity@5395cb5@0[17067])/@0xca9cf4a io.flutter.view.FlutterView5395cb5 VFED..... ......ID 0,0-1440,2900
Syncing files to device SM G960F...
D/SurfaceView(17067): surfaceCreated 1 #8 io.flutter.view.FlutterView5395cb5 VFED..... ......ID 0,0-1440,2900
D/mali_winsys(17067): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
D/SurfaceView(17067): surfaceChanged (1440,2900) 1 #8 io.flutter.view.FlutterView5395cb5 VFED..... ......ID 0,0-1440,2900
I/Choreographer(17067): Skipped 39 frames! The application may be doing too much work on its main thread.
D/ViewRootImpl@a7a19f9[MainActivity](17067): Relayout returned: old=[0,0][1440,2960] new=[0,0][1440,2960] result=0x3 surface=valid=true 508548042752 changed=false
I/OpenGLRenderer(17067): Davey! duration=814ms; Flags=1, IntendedVsync=626714985015335, Vsync=626715635015309, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=626715637655313, AnimationStart=626715637750275, PerformTraversalsStart=626715637758236, DrawStart=626715651163506, SyncQueued=626715655711967, SyncStart=626715655915390, IssueDrawCommandsStart=626715656392275, SwapBuffers=626715796396544, FrameCompleted=626715799700313, DequeueBufferDuration=11272000, QueueBufferDuration=584000,
D/ViewRootImpl@a7a19f9[MainActivity](17067): MSG_WINDOW_FOCUS_CHANGED 1 1
D/InputMethodManager(17067): prepareNavigationBarInfo() DecorView@97d1d3e[MainActivity]
D/InputMethodManager(17067): getNavigationBarColor() -855310
D/InputMethodManager(17067): prepareNavigationBarInfo() DecorView@97d1d3e[MainActivity]
D/InputMethodManager(17067): getNavigationBarColor() -855310
V/InputMethodManager(17067): Starting input: tba=example.com.nativecode05_example ic=null mNaviBarColor -855310 mIsGetNaviBarColorSuccess true , NavVisible : true , NavTrans : false
D/InputMethodManager(17067): startInputInner - Id : 0
I/InputMethodManager(17067): startInputInner - mService.startInputOrWindowGainedFocus
D/ViewRootImpl@a7a19f9[MainActivity](17067): MSG_RESIZED_REPORT: frame=Rect(0, 0 - 1440, 2960) ci=Rect(0, 96 - 0, 60) vi=Rect(0, 96 - 0, 60) or=1
D/InputTransport(17067): Input channel constructed: fd=96
D/InputMethodManager(17067): prepareNavigationBarInfo() DecorView@97d1d3e[MainActivity]
D/InputMethodManager(17067): getNavigationBarColor() -855310
V/InputMethodManager(17067): Starting input: tba=example.com.nativecode05_example ic=null mNaviBarColor -855310 mIsGetNaviBarColorSuccess true , NavVisible : true , NavTrans : false
D/InputMethodManager(17067): startInputInner - Id : 0
D/ContentValues(17067): Performing authorization...
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 153
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
I/chatty (17067): uid=10433(example.com.nativecode05_example) AsyncTask #2 identical 2 lines
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 153
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
I/chatty (17067): uid=10433(example.com.nativecode05_example) AsyncTask #2 identical 9 lines
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
I/chatty (17067): uid=10433(example.com.nativecode05_example) AsyncTask #2 identical 1 line
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
I/chatty (17067): uid=10433(example.com.nativecode05_example) AsyncTask #2 identical 5 lines
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Info; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/HelloDetails; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Roles; annotation class 153
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Roles; annotation class 156
I/chatty (17067): uid=10433(example.com.nativecode05_example) AsyncTask #2 identical 5 lines
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Roles; annotation class 156
W/ecode05_exampl(17067): Unable to resolve Lcom/spotify/protocol/types/Roles; annotation class 156
E/ContentValues(17067): "message":"Could not authenticate within 60 s."
E/ContentValues(17067): com.spotify.android.appremote.api.error.AuthenticationFailedException: "message":"Could not authenticate within 60 s."
E/ContentValues(17067): at com.spotify.android.appremote.api.LocalConnector.asAppRemoteException(LocalConnector.java:131)
E/ContentValues(17067): at com.spotify.android.appremote.api.LocalConnector.access$000(LocalConnector.java:35)
E/ContentValues(17067): at com.spotify.android.appremote.api.LocalConnector$1.onConnectionFailed(LocalConnector.java:111)
E/ContentValues(17067): at com.spotify.android.appremote.internal.SdkRemoteClientConnector$ConnectionTask.onPostExecute(SdkRemoteClientConnector.java:142)
E/ContentValues(17067): at com.spotify.android.appremote.internal.SdkRemoteClientConnector$ConnectionTask.onPostExecute(SdkRemoteClientConnector.java:75)
E/ContentValues(17067): at android.os.AsyncTask.finish(AsyncTask.java:695)
E/ContentValues(17067): at android.os.AsyncTask.access$600(AsyncTask.java:180)
E/ContentValues(17067): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
E/ContentValues(17067): at android.os.Handler.dispatchMessage(Handler.java:106)
E/ContentValues(17067): at android.os.Looper.loop(Looper.java:214)
E/ContentValues(17067): at android.app.ActivityThread.main(ActivityThread.java:6986)
E/ContentValues(17067): at java.lang.reflect.Method.invoke(Native Method)
E/ContentValues(17067): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/ContentValues(17067): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
E/ContentValues(17067): Caused by: com.spotify.protocol.client.error.RemoteClientException: "message":"Could not authenticate within 60 s."
E/ContentValues(17067): at com.spotify.protocol.client.RemoteWampClient.getRemoteClientException(RemoteWampClient.java:139)
E/ContentValues(17067): at com.spotify.protocol.client.RemoteWampClient.access$200(RemoteWampClient.java:16)
E/ContentValues(17067): at com.spotify.protocol.client.RemoteWampClient$1.onAbort(RemoteWampClient.java:44)
E/ContentValues(17067): at com.spotify.protocol.client.WampRouterImpl.routeAbort(WampRouterImpl.java:100)
E/ContentValues(17067): at com.spotify.protocol.client.WampRouterImpl.route(WampRouterImpl.java:26)
E/ContentValues(17067): at com.spotify.protocol.client.AppProtocolCommunicator.onData(AppProtocolCommunicator.java:78)
E/ContentValues(17067): at com.spotify.android.appremote.internal.RemoteServiceIo.handleMessage(RemoteServiceIo.java:113)
E/ContentValues(17067): at com.spotify.android.appremote.internal.RemoteServiceIo.access$000(RemoteServiceIo.java:47)
E/ContentValues(17067): at com.spotify.android.appremote.internal.RemoteServiceIo$IncomingHandler.handleMessage(RemoteServiceIo.java:91)
E/ContentValues(17067): ... 6 more
I/flutter (17067): test
D/InputMethodManager(17067): prepareNavigationBarInfo() DecorView@97d1d3e[MainActivity]
D/InputMethodManager(17067): getNavigationBarColor() -855310
V/InputMethodManager(17067): Starting input: tba=example.com.nativecode05_example ic=null mNaviBarColor -855310 mIsGetNaviBarColorSuccess true , NavVisible : true , NavTrans : false
D/InputMethodManager(17067): startInputInner - Id : 0
I/InputMethodManager(17067): startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport(17067): Input channel constructed: fd=97
D/InputTransport(17067): Input channel destroyed: fd=96
D/SurfaceView(17067): windowStopped(true) false 5395cb5 of ViewRootImpl@a7a19f9[MainActivity]
D/SurfaceView(17067): show() Surface(name=SurfaceView - example.com.nativecode05_example/example.com.nativecode05_example.MainActivity@5395cb5@0[17067])/@0xca9cf4a io.flutter.view.FlutterView5395cb5 VFED..... ........ 0,0-1440,2900
D/SurfaceView(17067): surfaceDestroyed callback.size 1 #1 io.flutter.view.FlutterView5395cb5 VFED..... ........ 0,0-1440,2900
W/libEGL (17067): EGLNativeWindowType 0x7667d36010 disconnect failed
D/SurfaceView(17067): destroy() Surface(name=SurfaceView - example.com.nativecode05_example/example.com.nativecode05_example.MainActivity@5395cb5@0[17067])/@0xca9cf4a io.flutter.view.FlutterView5395cb5 VFED..... ........ 0,0-1440,2900
D/ViewRootImpl@a7a19f9[MainActivity](17067): MSG_WINDOW_FOCUS_CHANGED 0 1
D/InputMethodManager(17067): prepareNavigationBarInfo() DecorView@97d1d3e[MainActivity]
D/InputMethodManager(17067): getNavigationBarColor() -855310
D/SurfaceView(17067): onWindowVisibilityChanged(8) false 5395cb5 of ViewRootImpl@a7a19f9[MainActivity]
W/libEGL (17067): EGLNativeWindowType 0x7667d35010 disconnect failed
D/OpenGLRenderer(17067): eglDestroySurface = 0x765347ca00, 0x7667d35000
D/ViewRootImpl@a7a19f9[MainActivity](17067): Relayout returned: old=[0,0][1440,2960] new=[0,0][1440,2960] result=0x5 surface=valid=false 0 changed=true
【问题讨论】:
【参考方案1】:您好,spotify_sdk 包完全符合您的要求。免责声明我是这个包的开发者:)
【讨论】:
【参考方案2】:您可以将此代码用于 Spotify API。它也可以用于其他 API 调用。这里使用的是flutter_web_auth 0.1.2 包。比较容易。
void authenticate() async
// Present the dialog to the user
final result = await FlutterWebAuth.authenticate(
url:
"https://accounts.spotify.com/authorize?client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx&redirect_uri=yourname:/&scope=user-read-currently-playing&response_type=token&state=123",
callbackUrlScheme: "yourname",
);
// Extract token from resulting url
final token = Uri.parse(result);
String at = token.fragment;
at = "http://website/index.html?$at"; // Just for easy persing
var accesstoken = Uri.parse(at).queryParameters['access_token'];
print('token');
print(accesstoken);
添加到 AndroidManifest.xml android\app\src\main
...
</activity>
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourname" />
</intent-filter>
</activity>
</application>
</manifest>
【讨论】:
以上是关于Flutter:如何将原生 SDK(Spotify Android SDK)添加到应用程序中?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Flutter web 调用原生 Android 代码。?
如何使用 Spotify API 和 Spotify SDK [关闭]
使用android sdk登录spotify时如何获取帐户类型