I was testing this method to remove tracks from a playlist. Basically I modified the demo project "simple track playback" provided with the SDK. I wanted to remove the track form the playlist when you hit fastForward. I changed the fastForward method this way but it's not doing anything, and error is nil.
-(IBAction)fastForward:(id)sender {
if([self.player isPlaying] && self.currentPlaylistSnapshot){
SPTAuth *auth = [SPTAuth defaultInstance];
[self.currentPlaylistSnapshot removeTracksFromPlaylist:#[self.player.currentTrackURI]
withAccessToken:auth.session.accessToken
callback:^(NSError *error) {
if (error != nil) {
NSLog(#"*** Failed to remove track : %#", self.titleLabel.text);
return;
}
}];
}
[self.player skipNext:nil];
}
self.currentPlaylistSnapshot is the one I've got from the handleNewSession method.
There's also a static method apparently offering something similar which I have't tried yet.
createRequestForRemovingTracks:fromPlaylist:withAccessToken:snapshot:error:
According to the documentation both options are implemented asynchronously and will take seconds to reflect the results in the server but I'm suspecting that there's either something wrong or I'm just missing to do an actual request to push the changes on the local snapshot maybe?
Documentation:
https://developer.spotify.com/ios-sdk-docs/Documents/Classes/SPTPlaylistSnapshot.html#//api/name/removeTracksWithPositionsFromPlaylist:withAccessToken:callback:
ios sdk:
https://github.com/spotify/ios-sdk
I solved my issue by reseting simulator + adding SPTAuthPlaylistModifyPublicScope (which I fogot to do...)
auth.requestedScopes = #[SPTAuthStreamingScope, SPTAuthPlaylistModifyPublicScope];
Related
I am using react-native-firebase:: 5.6.0, I am having issue while getting initial link for iOS device. On android it's working fine. I am using "Firebase Dynamic Links" to redirect user inside login screen of my app if in case he is not logged in inside app, otherwise just opening app if he is already logged in.
It's working for android app but having an issue with ios app. I have used two function one is the get dynamic link if app is closed "getInitialLink" and another one is to check when app is opened "onLink".
This is function I am using after closing splash screen, only called once when opening app from closing state.
firebase.links().getInitialLink().then((url) => {
if (url && url === 'https://mycustomdomain.co.in') {
navigationToScreen(AUTH, INITIAL_SCREEN);
} else {
// INITIALIZE APP HERE
}
});
If app already opened I am getting dynamic link url value inside this function::
this.unsubscribeHandleOpenAppDynamicLinks = firebase.links().onLink(async (url) => {
let isLoggedIn = await AsyncStorage.getItem(LocalStorageKeys.IS_LOGGEDIN);
if (url) {
if ( isLoggedIn !== 'yes' && url === 'https://mycustomdomain.co.in') {
navigationToScreen(AUTH, INITIAL_SCREEN);
}
}
});
and clearing that listener on componentWillUnmount:: this.unsubscribeHandleOpenAppDynamicLinks();
In case of iOS only "onLink" function is working and I am
getting url value as "undefined". getInitialLink() function will
returns the URL that the app has been launched from. If the app was
not launched from a URL the return value will be null, but I am
getting "undefined" even when launching an app from url in case of iOS
only. I am getting url inside onLink() in case of iOS when app is
launched. Why this is happening??
Please suggest what I am doing wrong here.
If getInitialLink method does not work, it is either because of improper linking or due to Expo runtime. As an alternative, use Linking.getInitialURL method to get the initial URL. This requires a little bit of native code as well. This is because Linking module does not know how to interpret the shortened URL. So, we call the resolveShortLink method of Firebase SDK to get the embedded deep link. Once we receive the embedded deep link, we can handle it as usual in our app.
The native source code is documented in this article. But for completeness, I will post it here.
#import "FDLResolver.h"
#import <React/RCTLog.h>
#implementation FDLResolver
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(resolveShortLink:(NSString *)shortLink :(RCTPromiseResolveBlock)resolve
:(RCTPromiseRejectBlock)reject)
{
id completion = ^(NSURL *_Nullable dynamicLink, NSError *_Nullable error) {
if (!error && dynamicLink) {
resolve(dynamicLink.absoluteString);
} else {
reject(#"Error", #"Error in getting dynamic link", error);
}
};
NSURL *shortLinkURL = [NSURL URLWithString:shortLink];
[[FIRDynamicLinks dynamicLinks] resolveShortLink:shortLinkURL completion:completion];
}
#end
And Linking module code is below.
Linking.getInitialURL().then(url => {
if (url && url.includes('page.link')) {
const shortLink = url.replace('exps', 'https')
NativeModules.FDLResolver.resolveShortLink(shortLink)
.then(link => {
const linkParts = link.split('?')
const query = qs.parse(linkParts[1])
this.parseRouteUrl(query.deep_link_id)
})
}
})
I have used Google play game leaderboard in my iOS app.i am submitting score from my and fetch score from there. i am using following method to submit score
`[score submitScoreWithCompletionHandler: ^(GPGScoreReport *report, NSError *error) {
if (error) {
// Handle the error
} else {
// Analyze the report, if you'd like
}
}];`
and below code to present leaderboard
NSString *targetLeaderboardId = #"my id";
[[GPGLauncherController sharedInstance] presentLeaderboardWithLeaderboardId:targetLeaderboardId];
but fetching score takes to much time.is there any way to reload or refresh leaderboard data.
anyone have any idea!
Unfortunately, Google Play Games Services for iOS has been deprecated, so I would not recommend putting too much time into it. More information: https://android-developers.googleblog.com/2017/04/focusing-our-google-play-games-services.html
I am using M7/M8 chip's MotionActivity in a variety of ways, including for step counting. For step counting, I both query for the day's steps, and request ongoingly the step count as they occur realtime.
Currently before I do this I check [CMStepCounter isStepCountingAvailable], as well as a local override flag, before proceeding with this code. I assumed isStepCountingAvailable would return FALSE if authorization for motionActivity was not granted. This does not seem to be the case, it appears to be more of a hardware detection only. I cannot seem to find other methods that detect whether authorization was granted for this.
What this means is that startStepCountingUpdatesToQueue and queryStepCountStartingFrom both run, and return blocks, but always return an error code. Specifically CMErrorDomain code 105.
Is there a better way for me to determine if motionActivity has not been authorized? I've got some fallback code but I'd prefer a boolean check beforehand, instead of an error code in the return block.
if (self.useM7IfAvailable && [CMStepCounter isStepCountingAvailable]){
self.cmStepCounter = [[CMStepCounter alloc] init];
[self.cmStepCounter startStepCountingUpdatesToQueue:self.operationQueue updateOn:1.0 withHandler:^(NSInteger numberOfSteps, NSDate *timestamp, NSError *error){
if(!error){
// do something with numberOfSteps
} else {
// not authorized: CMErrorDomain code 105
}
}];
}
[self.cmStepCounter queryStepCountStartingFrom:dayStart to:dayEnd toQueue:_operationQueue withHandler:^(NSInteger numberOfSteps, NSError *error) {
if(!error){
// do something with numberOfSteps
} else {
// not authorized: CMErrorDomain code 105
}
}];
You're doing it correctly by checking for the error. Per the docs (https://developer.apple.com/library/ios/documentation/coremotion/reference/cmmotionmanager_class/index.html#//apple_ref/c/tdef/CMError) you'll receive back CMErrors with Error Code 105 like you've seen.
Unfortunately there's no way to check ahead-of-time to see if you're authorized or not, but this follows Apple's paradigms with other Core-level frameworks that require authorization, like CoreLocation. The reasoning is you can be in the middle of getting motion steps while in the background, and the user can then disable your motion access, which you'll have to react to that event in probably the same way you'd react to not being authorized in the first place.
I'm just developing Web Apps based on Cordova, but I have a problem: I want to include Spotify in a new App.
Spotify has the iOS SDK (beta) with a beginner Tutorial. That worked fine (On App load Start the Auth).
Now I would like to implement that in my WebApp using Cordova.exec(); (Not on load - I would like to Auth on Button Click (Triggered by JavaScript).
I've generated a Cordova Plugin for that - that worked. And i can trigger a Method via Cordova.exec();.
This Method get triggered:
- (BOOL)startSpotifyAuth:(CDVInvokedUrlCommand*)command {
// Create SPTAuth instance; create login URL and open it
NSURL *loginURL = [[SPTAuth defaultInstance] loginURLForClientId:kClientId declaredRedirectURL:[NSURL URLWithString:kCallbackURL] scopes:#[#"login"]];
// Opening a URL in Safari close to application launch may trigger an iOS bug, so we wait a bit before doing so.
// [UIApplication performSelector:#selector(openURL:) withObject:loginURL afterDelay:0.1];
NSLog(#"*** GOT THIS IN DEBUG CONSOLE ***");
// Ask SPTAuth if the URL given is a Spotify authentication callback
if ([[SPTAuth defaultInstance] canHandleURL:loginURL withDeclaredRedirectURL:[NSURL URLWithString:kCallbackURL]]) {
NSLog(#"*** GOT THIS - NOT - IN DEBUG CONSOLE ***");
// Call the token swap service to get a logged in session
[[SPTAuth defaultInstance] handleAuthCallbackWithTriggeredAuthURL:loginURL tokenSwapServiceEndpointAtURL:[NSURL URLWithString:kTokenSwapURL] callback:^(NSError *error, SPTSession *session)
{
if (error != nil) {
NSLog(#"*** Auth error: %#", error);
return;
}
// Call the -playUsingSession: method to play a track
[self playUsingSession:session];
}];
return YES;
}
return NO;
}
As you can see by the Debug Outputs: I did not get inside the if(). But I don't know why: The loginURL looks correct.
You're using the wrong URL in your if statement. At that point, you need to validate the URL that gets handed to your application after the user has been bounced out to Safari for authentication, NOT the one you generate using SPAuth.
Are you still having issues with your project? Maybe my Spotify iOS SDK plugin can help. I just published the first version to the plugin registry.
You can install the plugin via the cordova command line client: cordova plugin add com.timflapper.spotify.
Add the ios platform if you haven't already done so: cordova platform add ios.
The following code is a simple example of how to authenticate with Spotify and play a single track:
var session, player;
var urlScheme = 'your-custom-url-scheme';
var clientId = 'your-own-client-id';
function onDeviceReady() {
spotify.authenticate(urlScheme, clientId, 'token', authDone);
}
function authDone(error, sess) {
if (error) return console.log("ERROR!", error);
console.log(sess);
session = sess;
player = spotify.createAudioPlayer(clientId);
player.login(session, function(error) {
if (error) return console.log(error);
player.play('spotify:track:2DlfLPbXH5ncf56Nytxd4w', function(error) {
if (error) return console.log(error);
});
});
}
document.addEventListener('deviceready', onDeviceReady, false);
I'm having the devils own time with Game Kit programmatic matching, and can only assume that despite reading all the tutorials I can lay my hands on... I've got the flow wrong somewhere.
Sign in to the Sandbox works fine, the app is being distributed with an App ID specific profile that is Game Center enabled. It all seems to work fine except that it never finds another "nearby" player.
The code below is my authentication handler, which is called correctly, but as I say despite it logging "Starting browser for nearby players", none are ever reported, blue tooth on same wifi network etc etc etc. Utterly perplexed as to what I am doing wrong.
-(void) authenticationHandler{
if ([_currentScene conformsToProtocol:#protocol(BOMScene)]){
MyScene<BOMScene> *theScene = (MyScene<BOMScene> *) _currentScene;
//Make sure the current scene gets the message that they are now authenticated
if ([GKLocalPlayer localPlayer].isAuthenticated){
[theScene localPlayerAuthenticated];
} else {
[theScene localPlayerDeauthenticated];
}
}
NSLog(#"Game Center Status Change: %#", _localPlayer.authenticated ? #"Available" : #"Not Available");
if (_localPlayer.authenticated){
if (!_matchMaker){
_matchMaker= [GKMatchmaker sharedMatchmaker];
NSLog(#"Starting to browser for nearby players");
[_matchMaker startBrowsingForNearbyPlayersWithReachableHandler:^(NSString *playerID, BOOL reachable) {
NSLog(#"Nearby player %# is %#",playerID, reachable ? #"available" : #"no longer available");
if (reachable){
[_nearbyPlayers addObject:playerID];
} else {
[_nearbyPlayers removeObject:playerID];
}
}];
}
} else {
_matchRequest = nil;
[_matchMaker stopBrowsingForNearbyPlayers];
[_nearbyPlayers removeAllObjects];
_matchMaker = nil;
}
You need to install an invitation handler.
Please see my answer here for a full breakdown:
Some startBrowsingForNearbyPlayersWithReachableHandler questions