UILocalNotification Not Working ... No Vibration on iPhone 4 iOS 4.3 - iphone

I would write as much as I could write here, but the Title pretty much says it all. I've tested it in several different situations:
1) Phone on, silent mode off, app on, in foreground, screen unlocked
I know that this goes through app delegate's didReceiveLocalNotification and didn't expect a sound or vibration, except for the handling code that I included under didReceiveLocalNotification. The handling code actually called
NSURL *Sound = [[NSBundle mainBundle] URLForResource: self.currentSoundPVC
withExtension: #"caf"];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (soundFileURLRef,&soundFileObject);
AudioServicesPlayAlertSound (soundFileObject);
and that actually works! It plays a sound and vibrates the phone simultaneously.
2) phone on, silent mode off, app on, in background, screen unlocked
Now, I set up my uilocalnotification alarms in app delegate's applicationDidEnterBackground, using the following code
NSString *Sound = [self.currentSoundPVC stringByAppendingString:#".caf"];
UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
alarm.fireDate = [NSDate dateWithTimeIntervalSinceNow:seconds];
[alarm setSoundName:Sound];
[[UIApplication sharedApplication] scheduleLocalNotification:alarm];
and this only partially works! The sound gets played but there is NO VIBRATION! Now, this I think is a bug because I am quoting from the apple developer website,
http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html, Scheduling the Delivery of Local Notifications section:
"When the notification is sent and the sound is played, the system also triggers a vibration on devices that support it. "
Now, obviously that is NOT THE CASE for my iPhone and obviously the simulator doesn't vibrate, so I can't test this and would like to have this addressed in the developer community!
3) phone on, silent mode off, app on, in foreground, screen locked
Same as #2
4) phone on, silent mode off, app on, in background, screen locked
Same as #2
5) phone on, silent mode off, app off (background process deleted)
Same as #2, because the uilocalnotifications were never cancelled, so the iOS still thinks they are valid.
6) phone on, silent mode on, app on, in background, screen unlocked
no sound, no vibration, NOTHING! This sucks! I would have hoped that apple would have come up with something that works straight out of the box, as usual!

These are the options and the effects (all assume the volume is set to some reasonable value):
Option 1:
Configuration:
[Developer controlled] Valid sound name set in UILocalNotification = No
[User controlled] Notification Centre setting for the app: Sound = N/A
[User controlled] Silent mode (switch on side of iPhone) = N/A
Behaviour:
Sound played with notification = No
Vibrate with notification = No
Option 2:
Configuration:
Valid sound name set in UILocalNotification = Yes
Notification Centre setting for the app: Sound = Off
Silent mode (switch on side of iPhone) = N/A
Behaviour:
Sound played with notification = No
Vibrate with notification = No
Option 3:
Configuration:
Valid sound name set in UILocalNotification = Yes
Notification Centre setting for the app: Sound = On
Silent mode (switch on side of iPhone) = No (Not selected)
Behaviour:
Sound played with notification = Yes
Vibrate with notification = No
Option 4:
Configuration:
Valid sound name set in UILocalNotification = Yes
Notification Centre setting for the app: Sound = On
Silent mode (switch on side of iPhone) = Yes (Selected)
Behaviour:
Sound played with notification = No
Vibrate with notification = Yes

the following works with a sound and a vibration:
// Create a new notification
UILocalNotification * notif = [[[UILocalNotification alloc] init] autorelease];
if (notif)
{
notif.repeatInterval = 0;
notif.alertBody = #"NOTIFICATION!!"];
notif.soundName = #"sound.caf";
notif.alertAction = NSLocalizedString(#"View", #"View");
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
}
I know this might sound a bit silly, but have you perhaps turned off vibration in your iPhone settings?

Sorry for posting this as an answer but my comment was too long to post under yours. So I just put a snippet there and the rest here. This was a reply to tony million's answer.
Hi Tony,
Thanks for your input, however I am not sure which of the things that you changed had an effect. If I am noting correctly you changed the following items:
1) scheduleLocalNotification --> presentLocalNotificationNow
2) explicitly setting UILN repeatInterval
3) explicitly setting UILN alertBody
4) explicitly setting UILN alertAction
Other than those four changes, I don't see anything else. Which of these causal changes would you think had the desired effect for you.
Lol...no need to feel like that was a silly question. Although, I did mention in my post, "silent mode on/off", I did not specify what that meant. I was talking particularly about the switch on the side of the phone. It didn't even occur to me to check the iPhone settings! Haha! So, it was a good question! Unfortunately, however, it wasn't turned off and it had successfully vibrated when in scenario #1 from OrigPost.

Related

Alarm clock with answer-to-disable on iOS

Apple resources contain a lot of informations but there's one thing which I can't clearly understand reading about audio and notification.
Is it possible to make an app, running in background which produce sound (even if phone is locked and/or silenced) and when it's happend user must solve eg. equation to turn it off?
p.s. For now I mostly use Cordova framework but Obj-C tip will also be nice.
Yes it is posssible.
You can use UILocalNotification for this.
Also apple allows apps that are playing music in background.
Please check these links for the background task feature:
ManagingYourApplicationsFlow
ios multitasking background tasks
How to handle background audio playing while ios device is locked or on another
You can change Local Notifications for NSTimers (keeping them alive in inactive mode with https://github.com/mruegenberg/MMPDeepSleepPreventer) and calculate the time interval for each alarm. That way you can then play an audio even with the screen locked and the sound off pasting this in your - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions:
// Let the sound run with the screen blocked
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
But you will have some problems:
The app must be playing an audio file each 10 seconds so it doesn´t deep sleep and kills all NSTimers.
Apple could reject your app for doing so.
You can´t close the app with the home button, otherwise, it won´t work.
You must open the app every time you need to use the alarm (you can´t schedule and forget).
When the alarm fires, you only have the lock screen of the iPhone and need to unlock it first and then stop the alarm from inside the app.
In Apple they don´t want competitors for their alarm clock app, that's for sure! Almost all the alarm clock apps you see in the App Store use this poor approach.

Set device volume - UILocalNotification - iphone in silent mode

How can i set volume of device(in silent mode) when UILocalNotification is generated when application is in background? I am working on alarm app, so sound has to be played in silent mode too and i am handling app alarm using local notification.
Badly stuck in this issue, not able to play alarm in silent mode.
Please help..
It is simply not possible. The UILocalNotification popup and sound are generated by another system process, and that process observes the device silent mode, so it won't play the notification sound if the device is on silent.
if you want your alarm clock app to play the alarm sound even when device is in silent mode, you will have to play the alarm sound right from your app. To do that, you will need to keep your app running in the background, then you will have to play the alarm sound file while in the background. The later can be done by specifying "audio" that the "Required background modes" property in your info.plist (you will have to add that property to your plist file)
Now, using AVAudioPlayer, there is a way to play sound even when device is silent by setting the Audio session category like this:
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
Hope this helps.
You have to realize that local notifications are triggered even your app is killed. That leads me to conclusion that it is probably not possible to do that.
But you can try that like this:
UInt32 sessionCategory = kAudioSessionCategory_AmbientSound;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
right before you make your audio session active.

MPMoviePlayerController background audio issue in iOS5

I have an App that does the pretty standard operation:
It plays audio (streamed or in filesystem) when the app is in 1) Foreground mode, 2) Screen locked state 3)Background mode.
This was working fine in all iOS prior to iOS5.
I have been using MPMoviePlayerController (Because it can play streamed and local file system audio)
I have the following setup:
info.plist has Background Mode set to "Audio"
I have Audiosession setup as shown at http://developer.apple.com/library/ios/#qa/qa1668/_index.html
NSError *activationError = nil;
AVAudioSession *mySession = [AVAudioSession sharedInstance];
[mySession setCategory: AVAudioSessionCategoryPlayback error: &activationError];
if (activationError) { /* handle the error condition */ }
[mySession setActive: YES error: &activationError];
if (activationError) { /* handle the error condition */ }
I have background timer enabled that gets stopped at the end of audio playback
UIBackgroundTaskIdentifier newId = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:NULL];
I have the Moveplayer's useApplicationAudioSession = NO
I have subscribed to the following events to detect and handle various playback state and to start a new audio file at the end of current file.
MPMoviePlayerLoadStateDidChangeNotification
MPMoviePlayerPlaybackDidFinishNotification
MPMoviePlayerPlaybackStateDidChangeNotification
MPMoviePlayerNowPlayingMovieDidChangeNotification
Problem:
With this the audio starts to play and when the application is put to background state or if the phone is locked, the audio continues to play. But, after when I start another audio file,
I start getting PlaybackDidFinishNotification immediately with the state set to Playback ended (But the file was never played)
The same code plays audio files in foreground mode (After the current audio file ends, the next file is started without any problem)
Is there anything new in iOS5 I should be doing to get this to work? I read through the MPMoviePlayerController class reference and I couldn't see anything specific for iOS5.
Thanks in advance.
Finally figured out the issue. This is solved in this post in apple dev forums (needs login to see). That post was applicable to AVPlayer but also fixes the problem with MPMoviePlayerController as well.
Basically, this is an excerpt from that post:
your app must support remote control events! These are the audio
controller interface prex/nex/play/pause on the left of the multitask
switcher taskbar (not sure about the proper name of the thing). You
to this ensuring your view becomes First Controller and then calling
> [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
in viewDidLoad. Once you do this, your Player will no longer return
NO!!
My situation was different and I'm only answering here (and in the other SO question) to help future searchers on this error message. This does not answer the original question.
My app plays a sound OR a song but when I first coded it could play both. And in testing I always tested with a song. I played the song in the usual way:
self.musicQuery = [MPMediaQuery songsQuery];
[_musicQuery addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:selectedSongID forProperty:MPMediaItemPropertyPersistentID comparisonType:MPMediaPredicateComparisonEqualTo]];
[_musicQuery setGroupingType:MPMediaGroupingTitle];
[_myPlayer setQueueWithQuery:_musicQuery];
[_myPlayer play];
Weeks passed and I started testing with the sound, played with AVAudioPlayer. My app started freezing for 5 seconds and I'd get the MediaPlayer: Message playbackState timed out message in the Console.
It turns out that passing a query that was empty was causing the freeze and the message. Changing my app's logic to only play a song when there was a song to play fixed it.

iOS 4 Alarm Clock App with Multitasking Support

I'm making an alarm clock app with multitasking support. However, I'm stuck with some limitations of the sdk.
I need to play selected alarm sound whenever the alarm time comes with some properties set by the user.
These properties:
- Alarm sound can be a music from the user's iPod library, and also some sound files in application bundle.
- Alarm sound can be set to play as progressive.
Moreover, alarm sound must be played in background in a loop until the user cancels or wakes the app.
First logical thing that came to my mind was to use local notifications, but with local notifications you can play sound files that are only in app bundle(not iPod music) and that are at most 30 seconds long. Also you are not get notified when the user cancels the notification alert, iOS just stops playing your sound.
Now I'm thinking of using background audio playing option and play silence until the alarm time, and then play the alarm sound while also showing a local notification without sound. But again how will I know if user cancelled the local notification alert and stop playing audio. However according to Apple's documentation iPod music playing(and use of shared resources) is still not allowed for an app that is playing background audio.
I also can't understand how some other apps are doing some of these features. For example, Night Stand HD can play iPod music while in the background, and an app named "Progressive Alarm Clock" can play progressive sound while in the background.
Any ideas and suggestions on these issues? Any of your help will be greatly appreciated
I would say what you want to do is not possible with the current restrictions of iOS. That said you can probably fake a progressive alarm by doing what the developer of Progressive Alarm Clock do to play the progressive alarm. By scheduling many local notifications, one after each other. He has divided the alarm sounds into chunks of say 10 s each with progressive volume levels. This is a very crude example to show how the progressive alarm can be faked.
UILocalNotification *notif1 = [[UILocalNotification alloc] init];
notif1.fireDate = [NSDate dateWithTimeIntervalSinceNow:15];
notif1.soundName = UILocalNotificationDefaultSoundName;
notif1.alertBody = #"Alarm";
[[UIApplication sharedApplication] scheduleLocalNotification:notif1];
[notif1 release];
UILocalNotification *notif2 = [[UILocalNotification alloc] init];
notif2.fireDate = [NSDate dateWithTimeIntervalSinceNow:20];
notif2.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:notif2];
[notif2 release];
This will first display a notification and play the default sound after 15 seconds. After 5 seconds more the sound will be played again. By having a bunch of sound files where the volume is increasing the progressive sound can be faked just by scheduling more local notifications. This will of course only work if you have an alarm sound that can be easily divided into chunks, just like the bells in Progressive Alarm Clock. Unfortunately you can't cancel the alarm by tapping cancel in the notification. You have to start the application to do that.
Whatever the Progressive Alarm Clock developer is doing, it's not what Robert Höglund is describing, AFAIK, since the alarm will sound even if the phone is in silent, and UILocalNotification doesn't seem to have any way to allow for this. In addition, if you kill the app manually while an alarm is pending, the app will notify you that it needs to relaunch. This seems to suggest that it must be somehow running in the background.

What happens to an iPhone app when iPhone goes into stand-by mode?

My app uses NSTimer and it appears that NSTimer doesn't fire when the iPhone goes into the stand-by mode (either by pressing the hardware button or by the idle timer).
When I activate the iPhone again, my app is still in the foreground. What happens to third party apps when the iPhone is the stand-by mode?
Although it's not evident here, I believe the original poster did find an answer to his question by starting a thread (available here) in the iPhone Developer Forums (which I eventually had to find myself because the information wasn't shared here).
In case someone else has the same question and finds the page in the future, here's a helpful response that was posted by someone on the Apple forum called "eskimo1" (which I have edited slightly such that it is easier to read without having the context provided by the entire original thread):
Regarding iPhone app status terminology, "active" does not mean "awake", it means "attached to the GUI". Think of it being analogous to "frontmost" in Mac OS X. When you lock the device your app deactivates but the device may or may not go to sleep
iPhone OS rarely sleeps if the device is connected to main power (i.e., via USB). It can sleep if running on battery, however.
A short time after the screen is locked (20 seconds according to Oliver Drobnik), the device sleeps. This is like closing the lid on your laptop; all activity on the main CPU halts.
This does not happen if the device is playing audio in the right audio session. See DTS Q&A QA1626 "Audio Session - Ensuring audio playback continues when screen is locked" for details.
Note that the idleTimerDisabled property (which can be turned on to prevent the screen from turning off while the app is running) is about locking the screen after user inactivity. It's not directly related to system sleep (it's indirectly related in that the system may sleep shortly after it's locked).
See Application Interruptions in the iPhone OS Programming Guide, especially the applicationWillResignActive and applicationDidBecomeActive events. (The whole guide is certainly worth reading.) When You ignore the events, the timer seems to go on for a while and then stops. Sounds logical, the application could easily drain the battery if kept running. And what exactly happens to the application? I guess it simply does not get any CPU time – it freezes and only thaws when You turn the machine back “on.”
My first advice is do not disable the idle timer, that is just a hack. If you want to keep a timer alive during UI events run the timer on the current run loop using NSCommonModes:
// create timer and add it to the current run loop using common modes
self.timer = [NSTimer timerWithTimeInterval:.1 target:self selector:#selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
I used the information on this post for a small sample that I was building. This is the code that I used when I initiated the playback to prevent the audio from stopping:
AudioSession.Category = AudioSessionCategory.MediaPlayback;
And when the application is done with the playback to reset to the original value:
AudioSession.Category = AudioSessionCategory.SoloAmbientSound;
The full sample is here:
http://github.com/migueldeicaza/monotouch-samples/tree/master/StreamingAudio/
I was faced with this issue recently in an app I am working on that uses several timers and plays some audio prompts and made two relatively simple changes:
In the AppDelegate I implemented the following methods and there mere presence allows the app to continue when the screen is locked
// this receives the notification when the device is locked
- (void)applicationWillResignActive:(UIApplication *)application
{
}
// this receives the notification that the application is about to become active again
- (void)applicationWillBecomeActive:(NSNotification *)aNotification
{
}
references: UIApplicationDelegate Protocol Reference & NSApplication Class Reference in the API doc (accessible via Xcode, just search for applicationWillBecomeActive).
Made the main viewcontroller class an AVAudioPlayerDelegate and used this code from Apple's "AddMusic" sample to make the audio alerts the app played mix nicely into the iPod audio etc...
I just dropped this code into a method that is called during viewDidLoad. If this interests you, you fall into the "who should read this doc" category for this: Audio Session Programming Guide
// Registers this class as the delegate of the audio session.
[[AVAudioSession sharedInstance] setDelegate: self];
// The AmbientSound category allows application audio to mix with Media Player
// audio. The category also indicates that application audio should stop playing
// if the Ring/Siilent switch is set to "silent" or the screen locks.
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
// Activates the audio session.
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
I believe your application should run normally when suspended. (think Pandora Radio)
Check to see if your timer is being deallocated due to your view being hidden or some other event occurring.