Detect when song stops playing - iphone

This seems like something really basic but how do I execute a function when a song ends? I am playing one item at at time, and when it ends (or if possible, 10 seconds before it ends) I would like to call a function that gets the next song from a webservice.
I think it's handled in the MPMusicPlayerControllerPlaybackStateDidChangeNotification notification but am not sure. For the record, this notification only needs to be when the song ends (not pauses).
All I have is this, which is the function for the above observer:
- (void) handle_PlaybackStateChanged: (id) notification
{
MPMusicPlaybackState playbackState = [musicPlayer playbackState];
}
How do I find out if the song has ended? Also, is it possible create an observer/function when there are 10 seconds left on the song?

When you receive the notification you can look up the playbackState property of the MPMusicPlayerController.
As for executing a function 10 seconds before the song ends, you could set up a timer to execute in the future based on the length of the song minus 10 seconds, you would need to cancel that timer if the user changes the playbackState or selects a different song.

Related

NSTimer stops in Background while power cable is disconnected

I have created GPS base Application.
In which App logged GPS data every 1 second.
App used the NSTimer to fetch GPS data every second.
This NSTimer is start in background. The NSTimer is start when app received the silent push notification from APNS.
I have seen a problem in iOS 7 that when Phone attached with power cable at that time timer call appropriately but without attached power cable timer stops while App in background.
Any inputs to resolve this issue greatly appreciated.
An NSTimer is not guaranteed to fire if your app is not in foreground. Once you unplug the cable the system puts your app into background to save battery.
Using an NSTimer is not the supported method to get location data. Your CLLocationManager will tell its delegate when there is a new location. No need to poll it.
If you need to track geolocation in background you need to declare location updates as a background mode from the capabilities tab in Xcode 5 target settings. Otherwise your location manager will stop delivering location updates once your app is not in foreground.
There are only few use cases that you can implement for foreground. If you don't want your application to be refused within review please don't use any hacks. Of course, you can use NSTimer in background, but it must be created in thread (runloop) of background task. But this background task lives for the only certain amount of time, so your timer must fire during this period. In other words, your first goal is to create background task, and only then you can use the timer. There are few cases suitable for your purpose (that allow you to create this task): 1.Monitor significant location changes or region 2.Fetch data (iOs 7). So please refer
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"BG fetch in action");
//the only 30 sec is allowed to perform all your actions
//during this period you can each second track GPS data
[self performSelector:#selector(finishBackgroundFetch:) withObject:completionHandler afterDelay:27];
[[NSNotificationCenter defaultCenter] postNotificationName:#"StartMyGPSRoutine" object:nil];
}
-(void)finishBackgroundFetch:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"BG fetch completion handler");
[[NSNotificationCenter defaultCenter] postNotificationName:#"ForceStopAnyBackgroundTaskCreatedWithStartMyGPSRoutine" object:nil];
completionHandler(UIBackgroundFetchResultNewData);
}
of your application delegate -- this will be useful in your case as well as monitor significant location changes.
You ought to put anywhere:
if ([[UIApplication sharedApplication] respondsToSelector:#selector(setMinimumBackgroundFetchInterval:)]) {
NSLog(#"Set Force BG interval to %ld", interval);
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:interval];
}
In my case I fetch the GPS data each 5 min so 27sec to complete this task is not so long. Anyway you can play with time intervals with XCode. Please refer Main Menu->Debug->Simulate Background Fetch

Requesting a call back or notification once avaudioplayer completes it's playback

I am working in audio player module where it takes one audio file and playing. I am using AvAudioPlayer to play my audio file, it's working as expected and I am getting call backs once finished the audio playback. I have implemented looping by numberOfLoops property with negative value so far it's good. In a case I need call back once the current audio finishes playing first time. Is there any possible way to get call back or observer to notify me my audio played first time.
My idea is that we can achieve this by running a timer. What is the best approach?
Generic:
Each time completion of audio play back expecting a notification even it has infinite loop also.
first make numberofloops=0
use this delegate method so this method will call,
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) appSoundPlayer successfully: (BOOL) flag
then in that method u can make numberofloops= -1 so that u can get first notification and after loop continues. and [player play]..
and if u write numberofloops= 0 in audioPlayerDidFinishPlaying and play then each time audioPlayerDidFinishPlaying will call like loop..and you can get notification for each..

Why does MPMusicPlayerController call its now playing item changed selector method twice?

I am writing a music playlist editing application for the iPhone.
I am subscribing to the MPMusicPlayerController
MPMusicPlayerControllerNowPlayingItemDidChangeNotificationand I am
getting a problem where the #selector method for this notification
is being called more than once when the nowPlayingItem: changes.
I have divided up each playlist into their own MPMediaItemCollection objets, and when one playlist is finished I load the next one, by calling -pause on the player, passing a new MPMediaItemCollectionto the music player controller via its -setQueueWithItemCollection: method. I then explicitly set the nowPlayingItem to an item of item of my own and finally I call -play.
[musicPlayer pause];
[musicPlayer setQueueWithItemCollection:[MPMediaItemCollection collectionWithItems:[selectedPrefs mediaItems]]];
musicPlayer.nowPlayingItem = [selectedPrefs.playbackItems objectAtIndex:selectedPrefs.nowPlayingIndex];
[musicPlayer play];
When I do this the #selector is called twice for the now playing item changing. I suspect this is because -setQueueWithItemCollection:automatically changes the now playing item to point to the first media item in the new collection, and then I am changing this item again before calling -play.
Many thanks.

How to know when the MPMoviePlayerController has been paused in iPhone?

I want to add an overlay view for my video when the video is paused by the user. Is there any way to get the pause notification from MPMoviePlayerController?
According to Apple Doc, there should be ways to do this but I can't find which notification should I use for this purpose.
Quote:
In addition to being notified when
playback finishes, interested clients
can be notified in the following
situations:
-When the movie player begins playing, is paused, or begins seeking forward
...
For more information, see the Notifications section in this reference.
I assume you know about delegates and protocols as a means of receiving callbacks?
There's another global mechanism called notifications too.
You can do this via
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateChanged)
name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
Then, within playbackStateChanged, you can fetch the playbackState
- (void) playbackStateChanged {
_player.playbackState; // reading the playback
}
The step of reading playbackstate directly from the player is specified in the docs
To get the current playback state, get the value of the playbackState property of the movie player object.

Time Touch Events Take in iPhone SDK

I am wondering how I would go about measuring the time in between touches inside a view in the iPhone SDK. I know that the first event triggered is touchesBegan: and then the last one triggered is touchesEnded:, however I just don't know how I would go about measuring the time that the user has touched the view for. For instance, if they keep their finder in the view for 2 seconds, it will automatically trigger function twoSeconds: or something like that.
Thanks for any help!
Use [NSDate date] to get the current date and time. Store it in touchesBegan:, and fetch the duration in touchesEnded: as this
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:beganDate];
You will now have the duration between the events measured in seconds in length.