Push Notifications - sound not working? - iphone

I've got an iPhone app that I'm working on that uses Push Notifications.
In the payload I'm specifying a few things:
message body
sound
action-loc-key because I don't want the user to be able to launch the app from the notification
The notification is getting to my iPhone just fine. It shows a message without buttons. So body and action-loc-key are working just fine. But, it's not playing any sound.
However, there are a couple of things I've noticed during troubleshooting:
if I implement application:didReceiveRemoteNotification, everything looks fine. The Dictionary argument contains a key for sound, whose value is indeed the name of the file I want to play.
The sound file itself "works" because if I play it inside of the app (using the SoundEffect class from the BubbleLevel sample) it works just fine.
Despite these two facts, the sound effect simply isn't playing.
In the settings app, everything looks right - Push is turned on for my app, and I have both "sounds" and "alerts" set to on as well.
The iPhone documentation center suggests using Quicktime to look at the format of the file. This is what it looks like.
Finally, if I look at the info for this file in XCode, it says the file type is simply the default, "file." From what I could tell there is no audio-caf option in the list. I tried audio-WAV (the sound engineer told me the original files were WAVs) but that didn't change anything.
In addition, the code:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// view controller set up stuff
// ...
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}

I should have posted the JSON as well, it turns out I was constructing it wrong. The reason it worked in didReceieveRemote notification is b/c I was parsing the JSON myself and the fact that I had stuff out of order didn't matter.

Related

just_audio: Why does my audio player work the first time but not the second time?

Tagging this with the appropriate tag so that the repo author can see it.
When my app uses an audio file saved on the user's phone, it works just fine the first time. It shows the audio source as:
justAudioPlayer.audioSource: Instance of 'ProgressiveAudioSource'
playerState: playing=true,processingState=ProcessingState.ready
When I hit the back button (Navigator.pop()) and then go back into the screen and try to play the audio source again, the audio source is now null:
justAudioPlayer.audioSource: null
playerState: playing=true,processingState=ProcessingState.idle
This is likely a simple programming error with your app's state management which, for example, results in your creating a new player instance instead of reusing the same instance.
(Copied from my comment above since you confirmed it was the correct answer)

Responding to events when device has been locked

I'm working on a radio alarm clock, and i have some issues.
I am using local notifications for the alarms, so it has a gentle fallback if the app is not running.
I am well aware of the limitations of the device, and i know what i can and cannot do when the device has gone into background.
But my question is this:
I have seen other apps starting an audio streamer when i've locked the device. How is this possible? May this be inside an execution-timeframe?
How is the best way to implement this? Is it any way i can activate a streaming session when the device is locked?
Edit
To clarify: I know how i make audio play in the background. But the issue is triggering the audio-playback when an local notification or some other event fires.
One app that seems to do this, is Radio Alarm Clock. I haven't tried it for long period of times yet. But it seems to do this. A video demo of the app: http://www.youtube.com/watch?v=KJQiFOcdBWk
Have you already declared your background task?
Support for some types of background execution must be declared in advance by the app that uses them. An app declares support for a service using its Info.plist file. Add the UIBackgroundModes key to your Info.plist file and set its value to an array containing one or more of the following strings:
audio — The app plays audible content to the user while in the background. (This content includes streaming audio or video content using AirPlay.)
iOS App Programming Guide - Implementing Long Running Background Tasks
You can add this by clicking on your main project icon, then under the Info tab you can add "Required Background Modes" to the "Custom iOS Target Properties" section. "App Plays Audio" will be one of the three default values.
Big Edit With New Answer:
If everything else is already in order, you can keep your app running in the background using the UIApplication method
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler
detailed here: UIApplication Class Reference
with an example here: Hour 21: Building Background-Aware Applications
This allows you to run an instance of NSTimer which triggers your music player. The difference between this approach and UILocalNotifications is that this method never lets the app fully enter the background mode, the music player exists the entire time which subverts the need to create it from the background, which looks to be impossible.
There may be limitations to how long of a timer you can set, I haven't tested this past 14 minutes out.

view capturing in background

we can easily capture a view(screenshot) programmatically in iPhone.
But i am trying to capture screen automatically after every 5 seconds.that also, can be done.
But my main objective is , to capture screen, even if the app is closed, i.e in background.
Apple doesn't allow to background process to run for a long time, but can we do it for 5-10 min in background.
Capturing screen,even if the app is closed.Ofcourse user can close this function, within the app.
Apple might reject this, but is this possible ?
Regards
This is possible but it's not easy. You can register you app (via a .plist setting) as being a media app, this will allow it to run in the background. This is normally to allow media apps to continue playing music when the app is sent to the background. However if you are careful you can get it to do other thing in there too.
In your plist under "Required Background Modes" add a key "Item 0" and set it to "App plays Audio". This will mean you can do it.
You will then have to using AVAudioPlayer, play a silent sound that is say 5mins long, and then register one of your controllers for the AVPlayerItemDidPlayToEndTimeNotification notification. Then when this calls back, you can have your bit of code that, first takes a screenshot, and then starts the sound again.
This is the general concept, look somewhere like :
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_background-audio/
for how to set up the audio playing.
Just a note: APPLE WILL REJECT THIS!
If you are making an app for personal use only, this is fine, but will never make it to the app store.
Hoep this sheds some light on your situation! :)

iPad SDK: Embedded YouTube movie plays fullscreen version behind UIWebView

I have a UIWebview within a UIScrollView. Within the webview I have an embedded YouTube movie. When I play the YouTube movie everything works fine, however, when I press the fullscreen button the movie starts playing behind the webview. Bringing the WebView to the front does not work, because I want the scrolling capabilities of the ScrollView to do horizontal scrolling.
Basically, you want to be able to detect when a movie starts playing fullscreen and arrange your views appropriately. Then, when the fullscreen playback ends you want to be able to get your views back to how they are.
The problem is there's no documented way to hook into or detect when a UIWebView triggers video playback in full screen.
I said 'documented way', because there are some notifications you can use to detect when a UIWebView triggers fullscreen playback. You can just listen out for them and rearrange your views accordingly. However, I don't necessarily recommend this, because they're undocumented and subject to change (in fact, they have a spelling mistake in them up until iOS 4.3, see answers below).
// For iOS 4.3 and above:
UIMoviePlayerControllerDidEnterFullscreenNotification
UIMoviePlayerControllerDidExitFullscreenNotification
// For iOS 4.2 and below:
UIMoviePlayerControllerDidEnterFullcreenNotification
UIMoviePlayerControllerDidExitFullcreenNotification // (note spelling mistake)
Finding these out was a bit of a pain - there are actually several more notifications that get triggered when a YouTube video in a UIWebView gets played back. To find them out you'll need to drop a breakpoint on all posting of notifications, and then manually inspect the memory locations of those notifications to figure out their string names. I don't actually think anyone has pulled these out before, because when I google them I get nothing. But they do work, promise!
I hope being able to get notified when the fullscreen playback is entered/exited will be helpful, with the massive caveat that Apple could change this undocumented behavior at any time. Your app won't get rejected outright for using them (because you're not calling any undocumented methods), and I've used it in shipping apps. But it's still not the best idea in the world...may be the only option you have though.
Edit: To clarify, based off the comment below: they're not constants, so you'd need to put them in quotes if you were registered for notifications.
For iOS 4.3+, Apple have changed the names of these notifications:
UIMoviePlayerControllerDidEnterFullcreenNotification now is UIMoviePlayerControllerDidEnterFullscreenNotification
UIMoviePlayerControllerDidExitFullcreenNotification now is UIMoviePlayerControllerDidExitFullscreenNotification
Please pay attention: The term "Fullcreen" has changed to "Fullscreen".
Thanks!
Just wanted to confirm that this works after playing around with it for awhile. You can get direct access to the view that the video is playing in. This is a blocks method of registering for the notification and pulling out the pertinent views.
Notice: You will need to delay adding subviews and/or access Apple internal subviews to remove the navbar for further customization.
[[NSNotificationCenter defaultCenter]
addObserverForName:#"UIMoviePlayerControllerDidEnterFullcreenNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *note){
MPMoviePlayerController *theMovieController = [note object];
UIView *theDestinationVideoView = [[note userInfo]
objectForKey:#"UIMoviePlayerControllerFullscreenViewUserInfoKey"];
}];

Playing videos in UIWebView broken in iOS4?

I have an app that's worked since version 2.0 of the SDK where I create and add a UIWebView and then load the URL of an .mov to play a movie. Ever since the early version of the 4.0 beta up until the 4.0 GM this has stopped working. When I load a movie now I get the following error: :Plug-in handled load" and the movie never displays.
Is this a known issue? Am I doing something wrong in 4.0?
I figured this out. It appears to be an issue with iOS4 not being backward compatible with a UIWebView created with 'init' rather than 'initWithFrame'. In 2.0 - 3.1.3, you could only show video in a UIWebview as full screen. I think this is why it didn't matter if you called 'init' -- the movie player would kick in and go fullscreen. However, in 3.2 and higher you can now inline video in a UIWebView so you have to call initWithFrame and give it something like [[UIScreen mainScreen] bounds] so there's a visible view. Not quite sure if this is bull or not but seems to be the case.
I got a situation of "this movie could not be played" when playing a video clip.
This happened when recorder was just used. And this would NOT happen when player was just used.
Then I set audio session category to kAudioSessionCategory_AmbientSound after recorder finished.
This problem was solved after I did that.
Simply just ignore it. No harm in doing so.
if (![error.localizedDescription isEqualToString:#"Plug-in handled load"])
At least in PhoneGap's ChildBrowser, the didFailLoadWithError method handles and displays this message. Simply don't display the error, problem solved, but in this specific case there are two 'done' buttons to press before you get back to the application.