Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose checkIfSpotifyAppIsActive on iOS #105

Merged
merged 4 commits into from
Jun 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ Have a look [in the example](example/lib/main.dart) for detailed insights on how
| Function | Description| Android | iOS | Web |
|---|---|---|---|---|
| connectToSpotifyRemote | Connects the App to Spotify | ✔ | ✔ | ✔ |
| getAuthenticationToken | Gets the Authentication Token that you can use to work with the [Web Api](https://developer.spotify.com/documentation/web-api/) |✔ | ✔ | ✔ |
| disconnect | disconnects the app connection |✔ | ✔ | ✔ |
| getAuthenticationToken | Gets the Authentication Token that you can use to work with the [Web Api](https://developer.spotify.com/documentation/web-api/) | ✔ | ✔ | ✔ |
| disconnect | Disconnects the app connection | ✔ | ✔ | ✔ |
| isSpotifyAppActive | Checks if the Spotify app is active | 🚧 | ✔ | 🚧 |

#### Player Api

Expand Down
3 changes: 2 additions & 1 deletion ios/Classes/SpotifySdkConstants.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation

public class SpotfySdkConstants
public class SpotifySdkConstants
{
//connecting
public static let methodConnectToSpotify = "connectToSpotify"
public static let methodGetAuthenticationToken = "getAuthenticationToken"
public static let methodDisconnectFromSpotify = "disconnectFromSpotify"
public static let methodCheckIfSpotifyAppIsActive = "isSpotifyAppActive"

//player api
public static let methodQueueTrack = "queueTrack"
Expand Down
84 changes: 44 additions & 40 deletions ios/Classes/SwiftSpotifySdkPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
}

switch call.method {
case SpotfySdkConstants.methodConnectToSpotify:
case SpotifySdkConstants.methodConnectToSpotify:
guard let swiftArguments = call.arguments as? [String:Any],
let clientID = swiftArguments[SpotfySdkConstants.paramClientId] as? String,
let clientID = swiftArguments[SpotifySdkConstants.paramClientId] as? String,
!clientID.isEmpty else {
result(FlutterError(code: "Argument Error", message: "Client ID is not set", details: nil))
return
}

guard let url = swiftArguments[SpotfySdkConstants.paramRedirectUrl] as? String,
guard let url = swiftArguments[SpotifySdkConstants.paramRedirectUrl] as? String,
!url.isEmpty else {
result(FlutterError(code: "Argument Error", message: "Redirect URL is not set", details: nil))
return
Expand All @@ -56,11 +56,11 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
connectionStatusHandler?.connectionResult = result


let accessToken: String? = swiftArguments[SpotfySdkConstants.paramAccessToken] as? String
let spotifyUri: String = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String ?? ""
let accessToken: String? = swiftArguments[SpotifySdkConstants.paramAccessToken] as? String
let spotifyUri: String = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String ?? ""

do {
try connectToSpotify(clientId: clientID, redirectURL: url, accessToken: accessToken, spotifyUri: spotifyUri, asRadio: swiftArguments[SpotfySdkConstants.paramAsRadio] as? Bool, additionalScopes: swiftArguments[SpotfySdkConstants.scope] as? String)
try connectToSpotify(clientId: clientID, redirectURL: url, accessToken: accessToken, spotifyUri: spotifyUri, asRadio: swiftArguments[SpotifySdkConstants.paramAsRadio] as? Bool, additionalScopes: swiftArguments[SpotifySdkConstants.scope] as? String)
}
catch SpotifyError.redirectURLInvalid {
result(FlutterError(code: "errorConnecting", message: "Redirect URL is not set or has invalid format", details: nil))
Expand All @@ -70,18 +70,18 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
return
}

case SpotfySdkConstants.methodGetAuthenticationToken:
case SpotifySdkConstants.methodGetAuthenticationToken:
guard let swiftArguments = call.arguments as? [String:Any],
let clientID = swiftArguments[SpotfySdkConstants.paramClientId] as? String,
let url = swiftArguments[SpotfySdkConstants.paramRedirectUrl] as? String else {
let clientID = swiftArguments[SpotifySdkConstants.paramClientId] as? String,
let url = swiftArguments[SpotifySdkConstants.paramRedirectUrl] as? String else {
result(FlutterError(code: "Arguments Error", message: "One or more arguments are missing", details: nil))
return
}
connectionStatusHandler?.tokenResult = result
let spotifyUri: String = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String ?? ""
let spotifyUri: String = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String ?? ""

do {
try connectToSpotify(clientId: clientID, redirectURL: url, spotifyUri: spotifyUri, asRadio: swiftArguments[SpotfySdkConstants.paramAsRadio] as? Bool, additionalScopes: swiftArguments[SpotfySdkConstants.scope] as? String)
try connectToSpotify(clientId: clientID, redirectURL: url, spotifyUri: spotifyUri, asRadio: swiftArguments[SpotifySdkConstants.paramAsRadio] as? Bool, additionalScopes: swiftArguments[SpotifySdkConstants.scope] as? String)
}
catch SpotifyError.redirectURLInvalid {
result(FlutterError(code: "errorConnecting", message: "Redirect URL is not set or has invalid format", details: nil))
Expand All @@ -90,14 +90,14 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
result(FlutterError(code: "CouldNotFindSpotifyApp", message: "The Spotify app is not installed on the device", details: nil))
return
}
case SpotfySdkConstants.methodGetImage:
case SpotifySdkConstants.methodGetImage:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let paramImageUri = swiftArguments[SpotfySdkConstants.paramImageUri] as? String,
let paramImageDimension = swiftArguments[SpotfySdkConstants.paramImageDimension] as? Int else {
let paramImageUri = swiftArguments[SpotifySdkConstants.paramImageUri] as? String,
let paramImageDimension = swiftArguments[SpotifySdkConstants.paramImageDimension] as? Int else {
result(FlutterError(code: "Arguments Error", message: "One or more arguments are missing", details: nil))
return
}
Expand All @@ -119,7 +119,7 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
}
result(imageData)
})
case SpotfySdkConstants.methodGetPlayerState:
case SpotifySdkConstants.methodGetPlayerState:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
Expand All @@ -136,41 +136,41 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
}
result(State.playerStateDictionary(playerState).json)
})
case SpotfySdkConstants.methodDisconnectFromSpotify:
case SpotifySdkConstants.methodDisconnectFromSpotify:
appRemote?.disconnect()
// appRemote?.connectionParameters.accessToken = nil
result(true)
case SpotfySdkConstants.methodPlay:
case SpotifySdkConstants.methodPlay:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let uri = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String else {
let uri = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String else {
result(FlutterError(code: "URI Error", message: "No URI was specified", details: nil))
return
}
let asRadio: Bool = (swiftArguments[SpotfySdkConstants.paramAsRadio] as? Bool) ?? false
let asRadio: Bool = (swiftArguments[SpotifySdkConstants.paramAsRadio] as? Bool) ?? false
appRemote.playerAPI?.play(uri, asRadio: asRadio, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodPause:
case SpotifySdkConstants.methodPause:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
appRemote.playerAPI?.pause(defaultPlayAPICallback)
case SpotfySdkConstants.methodResume:
case SpotifySdkConstants.methodResume:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
appRemote.playerAPI?.resume(defaultPlayAPICallback)
case SpotfySdkConstants.methodSkipNext:
case SpotifySdkConstants.methodSkipNext:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
appRemote.playerAPI?.skip(toNext: defaultPlayAPICallback)
case SpotfySdkConstants.methodSkipPrevious:
case SpotifySdkConstants.methodSkipPrevious:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
Expand All @@ -182,17 +182,17 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
}
result(true)
})
case SpotfySdkConstants.methodSkipToIndex:
case SpotifySdkConstants.methodSkipToIndex:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let uri = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String else {
let uri = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String else {
result(FlutterError(code: "URI Error", message: "No URI was specified", details: nil))
return
}
let index = (swiftArguments[SpotfySdkConstants.paramTrackIndex] as? Int) ?? 0
let index = (swiftArguments[SpotifySdkConstants.paramTrackIndex] as? Int) ?? 0

appRemote.contentAPI?.fetchContentItem(forURI: uri, callback: { (contentItemResult, error) in
guard error == nil else {
Expand All @@ -206,29 +206,29 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
appRemote.playerAPI?.play(contentItem, skipToTrackIndex: index, callback: defaultPlayAPICallback)
})

case SpotfySdkConstants.methodAddToLibrary:
case SpotifySdkConstants.methodAddToLibrary:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let uri = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String else {
let uri = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String else {
result(FlutterError(code: "URI Error", message: "No URI was specified", details: nil))
return
}
appRemote.userAPI?.addItemToLibrary(withURI: uri, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodRemoveFromLibrary:
case SpotifySdkConstants.methodRemoveFromLibrary:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let uri = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String else {
let uri = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String else {
result(FlutterError(code: "URI Error", message: "No URI was specified", details: nil))
return
}
appRemote.userAPI?.removeItemFromLibrary(withURI: uri, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodGetCapabilities:
case SpotifySdkConstants.methodGetCapabilities:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
Expand All @@ -245,29 +245,29 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {

result(State.userCapabilitiesDictionary(userCapabilities).json)
})
case SpotfySdkConstants.methodQueueTrack:
case SpotifySdkConstants.methodQueueTrack:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let uri = swiftArguments[SpotfySdkConstants.paramSpotifyUri] as? String else {
let uri = swiftArguments[SpotifySdkConstants.paramSpotifyUri] as? String else {
result(FlutterError(code: "URI Error", message: "No URI was specified", details: nil))
return
}
appRemote.playerAPI?.enqueueTrackUri(uri, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodSeekTo:
case SpotifySdkConstants.methodSeekTo:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let position = swiftArguments[SpotfySdkConstants.paramPositionedMilliseconds] as? Int else {
let position = swiftArguments[SpotifySdkConstants.paramPositionedMilliseconds] as? Int else {
result(FlutterError(code: "Position error", message: "No URI was specified", details: nil))
return
}
appRemote.playerAPI?.seek(toPosition: position, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodGetCrossfadeState:
case SpotifySdkConstants.methodGetCrossfadeState:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
Expand All @@ -283,29 +283,33 @@ public class SwiftSpotifySdkPlugin: NSObject, FlutterPlugin {
}
result(State.crossfadeStateDictionary(crossfadeState).json)
})
case SpotfySdkConstants.methodSetShuffle:
case SpotifySdkConstants.methodSetShuffle:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let shuffle = swiftArguments[SpotfySdkConstants.paramShuffle] as? Bool else {
let shuffle = swiftArguments[SpotifySdkConstants.paramShuffle] as? Bool else {
result(FlutterError(code: "Position error", message: "No URI was specified", details: nil))
return
}
appRemote.playerAPI?.setShuffle(shuffle, callback: defaultPlayAPICallback)
case SpotfySdkConstants.methodSetRepeatMode:
case SpotifySdkConstants.methodSetRepeatMode:
guard let appRemote = appRemote else {
result(FlutterError(code: "Connection Error", message: "AppRemote is null", details: nil))
return
}
guard let swiftArguments = call.arguments as? [String:Any],
let repeatModeIndex = swiftArguments[SpotfySdkConstants.paramRepeatMode] as? UInt,
let repeatModeIndex = swiftArguments[SpotifySdkConstants.paramRepeatMode] as? UInt,
let repeatMode = SPTAppRemotePlaybackOptionsRepeatMode(rawValue: repeatModeIndex)else {
result(FlutterError(code: "Position error", message: "No URI was specified", details: nil))
return
}
appRemote.playerAPI?.setRepeatMode(repeatMode, callback: defaultPlayAPICallback)
case SpotifySdkConstants.methodCheckIfSpotifyAppIsActive:
SPTAppRemote.checkIfSpotifyAppIsActive { isActive in
result(isActive)
}
default:
result(FlutterMethodNotImplemented)
}
Expand Down
3 changes: 3 additions & 0 deletions lib/platform_channels.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class MethodNames {
/// method name for [disconnectFromSpotify]
static const String disconnectFromSpotify = 'disconnectFromSpotify';

/// method name for [checkIfSpotifyAppIsActive]
static const String isSpotifyAppActive = 'isSpotifyAppActive';

/// method name for [getCrossfadeState]
static const String getCrossfadeState = 'getCrossfadeState';

Expand Down
23 changes: 20 additions & 3 deletions lib/spotify_sdk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ class SpotifySdk {
}
}

/// Checks if the Spotify app is active on the user's device. You can use this to determine if maybe you should prompt
/// the user to connect to Spotify (because you know they are already using Spotify if it is active). The Spotify app
/// will be considered active if music is playing.
/// Returns true if Spotify is active, othewise false.
/// This method is only supported on iOS.
///
/// Throws a [MissingPluginException] if the method is not implemented on
/// the native platforms.
static Future<bool> get isSpotifyAppActive async {
try {
return await _channel.invokeMethod(MethodNames.isSpotifyAppActive);
} on Exception catch (e) {
_logException(MethodNames.isSpotifyAppActive, e);
rethrow;
}
}

/// Gets the current [CrossfadeState]
///
/// Throws a [PlatformException] getting the crossfadeState failed
Expand Down Expand Up @@ -296,7 +313,7 @@ class SpotifySdk {

/// Subscribes to the [PlayerContext] and returns it.
///
/// Throws a [PlatformException] if this failes
/// Throws a [PlatformException] if this fails
/// Throws a [MissingPluginException] if the method is not implemented on
/// the native platforms.
static Stream<PlayerContext> subscribePlayerContext() {
Expand All @@ -316,7 +333,7 @@ class SpotifySdk {

/// Subscribes to the [PlayerState] and returns it.
///
/// Throws a [PlatformException] if this failes
/// Throws a [PlatformException] if this fails
/// Throws a [MissingPluginException] if the method is not implemented on
/// the native platforms.
static Stream<PlayerState> subscribePlayerState() {
Expand All @@ -336,7 +353,7 @@ class SpotifySdk {

/// Subscribes to the [ConnectionStatus] and returns it.
///
/// Throws a [PlatformException] if this failes
/// Throws a [PlatformException] if this fails
/// Throws a [MissingPluginException] if the method is not implemented on
/// the native platforms.
static Stream<ConnectionStatus> subscribeConnectionStatus() {
Expand Down