Take a picture after BTLE background notification fired - ios

I'm developing an app that runs in background mode, so that my app receives BT notifications from a BTLE accessory.
When I get a specific notification, I want to take a picture whether the app is running in background or foreground.
First question: Would the app be rejected by Apple because of taking photos in background mode?
Second question:
What would be the best option to do this?
At first I thought about using UIImagePickerController, but finally I'm using AVFoundation AVCam example because I do not need to show preview.
But, Third and last question: could I show a preview?
I have tried to use the following code. It works ok if app is running in foreground mode, but not for background mode:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"iPhone5Storyboard" bundle:nil];
AVCamViewController *camViewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"ViewControllerCamera"];
UIViewController *rootVC = [[(AppDelegate *) [[UIApplication sharedApplication] delegate] window] rootViewController];
[rootVC presentViewController: camViewController animated:YES completion:nil];
Many doubts.

First off, you cannot take a picture when the app is not in the foreground. That's just a core iOS limitation. (You could do it with a jailbroken iphone though).
As for the second part of your question, you AVFoundation is a great way to work with camera functionality. It's flexible on the view presentation and any type of filters you'd like to apply to the video stream. The AVCam example is a great example.
And for the third, that goes back to the first point. No matter what you use, you can't take pictures in the background unless it's in the foreground and the user has given permission.
I suggest submitting a local notification and asking the user to bring the app to the foregound when you want to take a picture. Probably not the news you wanted to hear, but that's how Apple intended it to be used.

Related

How to create a custom alarm wake up screen on iOS?

Is it possible to create a custom alarm wake up screen on iOS via Xcode, such as the carrot alarm app on the App Store? If so, could anyone point to some documentation or examples?
I'm pretty confused at the moment, because I don't understand how it can be done as long as the iPhone locks itself and the app stops working. This is my main concern, because locking the iPhone kills the app.
I would like to what's the best way to create a wake up screen like carrot app's one, avoiding all the screen lock problems. How did they do it?
Thanks
Using the code below you can disable the lock screen. You can place it in your viewDidLoad method.
[[UIApplication sharedApplication] setIdleTimerDisabled: YES];
As for creating the screen, I'd suggest picking up a book on iPhone development as it's a lot to explain in a follow-up message.

Display one thing on iPad and another on Apple Tv?

I have an app idea, but I'm not sure if it's possible.
I was wondering if I'm able to display one thing on the iPad ( or iPhone )
screen, and something totally different on the Apple Tv at the same time.
For example, a quiz app, where the question is displayed on the Apple Tv, and the multiple choices are listed on the iPad for the user to pick.
I'm not sure if this is possible or if you can only Mirror the iPad screen onto the Apple Tv.
If there is some "Proof of Concept" example code, I'd love to take a look.
Thank you so much.
Chris
Turns out that is is pretty simple to support two screens: the primary screen of the iOS device and a secondary screen (either an external display or mirroring on an Apple TV).
Based on information from the blog post Creating a Dual-Screen AirPlay Experience for iOS and Apple TV, you don't need to do much.
Basically you need to check the screens property from UIScreen. There are also notifications you should listen for (UIScreenDidConnectNotification and UIScreenDidDisconnectNotification) so you know if the number of screens changes while your app is running.
Once you have a second screen, you need to create a new window for it. Code like the following can be used:
if ([UIScreen screens].count > 1) {
if (!_secondWin) {
UIScreen *screen = [UIScreen screens][1];
_secondWin = [[UIWindow alloc] initWithFrame:screen.bounds];
_secondWin.screen = screen;
}
}
where _secondWin is a UIWindow ivar.
Once the window is setup, create a view controller, make it the window's root view controller, and show the window:
SomeViewController *vc = [[SomeViewController alloc] init...];
_secondWin.rootViewController = vc;
_secondWin.hidden = NO;
This is pretty much it other than proper handling of the notifications. Keep in mind that you can't get any touch events on the 2nd display so make sure whatever you show is basically display-only.
Depending on your app, you might have the 2nd screen/window being used throughout the lifetime of the app (as long as the 2nd screen is available any way). Or you might only create and use the 2nd window/screen under certain circumstances. When you don't setup the 2nd window/screen, your app will simply be mirrored to the 2nd display or Apple TV.
The last piece is to turn on mirroring to the Apple TV. This is done on the iOS device, not in the app.
The blog post I linked has a few more details worth reviewing.

Changing rootViewController in applicaitonWillEnterForeground

Long story short, I'm trying to change my iOS app's rootViewController on applicationWillEnterForeground:, like so:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
MyViewController *controller = [[MyViewController alloc] init];
self.window.rootViewController = controller;
}
However, when iOS performs the "zoom in" animation that is performed when an app is moved from the background to the foreground, it still shows the previous rootViewController's view. Then, as soon as the animation is complete, the app blasts the new rootViewController's view onto the screen.
One way to solve this is to simply move that code to - (void)applicationDidEnterBackground:, but the problem with this solution is that, in my app, there is no way to tell if a new rootViewController will be assigned until - (void)applicationWillEnterForeground:(UIApplication *)application (it is based on time passed since leaving the app).
How can I force the app to redraw before iOS performs the animation taking the app from the background to the foreground?
I believe this is not possible. The screen that iOS shows of your app when it comes into the foreground is actually a screenshot the system took when the app went into the background. There is no way to manipulate or replace that image at the time the app comes back into the foreground.
This behavior is partly documented in the Moving to the Background section of the iOS Application Programming Guide:
Apps can use their applicationDidEnterBackground: method to prepare for moving to the background state. When moving to the background, all apps should do the following:
Prepare to have their picture taken. When the applicationDidEnterBackground: method returns, the system takes a picture of your app’s user interface and uses the resulting image for transition animations. If any views in your interface contain sensitive information, you should hide or modify those views before the applicationDidEnterBackground: method returns.
Apple does not explicitly document that you cannot modify or replace this screenshot at a later time but neither do they say the opposite anywhere I know of.

iOS: Hiding sensitive information on the screen when app is backgrounded

When a foreground app gets backgrounded (e.g. Home button gets pressed), how can I change elements on the topmost view controller prior to when iOS takes a snapshot of it and starts the animation to show the next screen?
I ask because I'm writing an app requiring HIPAA compliance, and I am concerned that the snapshot that the OS takes in order to do this animation sometimes contains sensitive data which should not be visible even for a split second when the app gets foregrounded later.
I'm aware that view controllers have lifecycle methods such as viewWillDisappear which might be usable, but I have a lot of controllers and I'd rather just have something in my App Delegate to handle this (e.g. by adding an opaque full-screen UIImageView overlay) rather than having to write custom code for this in every last controller.
I tried putting overlay-generating code in applicationWillResignActive, and I've been digging with Apple's docs and Google, but it's not working. I suspect the screenshot gets taken before the app has a chance to update the screen.
Thanks!
Not sure about HIPAA's requirements about backgrounding and possibly leaving the user logged in for someone else to resume, but the safest sounds like it would be to add a key UIApplicationExitsOnSuspend with a boolean value of YES to info.plist.
That will prevent the app from backgrounding entirely, and restarts it (possibly triggering a login procedure) every time you go back to it.
Most (if not all) mobile banking applications I've tested do this for safety reasons.
I believe the answer is to not concern oneself with changing what's on the screen before the backgrounding animation begins, but to simply modify what's displayed on the screen once the app enters the background (i.e. inside of applicationDidEnterBackground: in your App Delegate.) This solved my problem.
My UIImageView overlay idea worked here, although I decided just to pop to the root view controller instead. Simpler that way. My root view doesn't have any sensitive info.
Here's what it looks like:
-(void)applicationDidEnterBackground:(UIApplication *)application {
UINavigationController *navigationController =
(UINavigationController *)self.window.rootViewController;
[navigationController popToRootViewControllerAnimated:NO];
...
}

go to another page in applicationDidEnterBackground in iOS in device

In my application, When the application goes to background I am calling a Passcode page (Passcode Page which does authentication).
My requirement is when the user launch the app from the foreground he will see the passcode page. If he enters the correct passcode then only he can see the rest pages.
In delegate.m file
- (void)applicationDidEnterBackground:(UIApplication *)application
{
PasscodeViewController *passcodeController = [[PasscodeViewController alloc] initWithNibName:#"PasscodeViewController" bundle:nil];
[navController pushViewController:passcodeController animated:YES];
}
When I am launching the application from the background then It is showing me the previous page( from which page I came to background ) for a fraction of second and after that Passcode page comes.
But I want to hide my confidential information from others (who doesn't know the passcode) that are shown in the previous page.
It is correctly working in Simulator but in Device it is not working properly.
Can you please guide me in that ?
OR
Is it the normal behavior of the iOS device ? What ever the page transition it will do, it will perform while the application is running in foreground.
I am not sure about that. Please tell me where I went wrong.
Thank you.
Every app I've used with a similar feature has operated as you describe, with the fractional-second flash before the lock view appears.
I think it's a matter of when UIKit thinks it needs to re-render... We had a similar case with a splash screen, but using applicationDidEnterBackground for adding the splash helped.
My idea is to avoid the animating, using
[navController pushViewController:passcodeController animated:NO];
Whenever your app goes background add a UIView with white background.
Whenever your app comes up push your PasscodeViewController view on top
Please add observers for UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification to do the above functionality
Also be sure to remove the Observers when your view disappears
When user enters correct passcode remove the UIView.
Try applicationWillResignActive:
- (void)applicationWillResignActive:(UIApplication *)application
{
PasscodeViewController* passcodeController = [[PasscodeViewController alloc] initWithNibName:#"PasscodeViewController" bundle:nil];
[navController pushViewController:passcodeController animated:YES];
}
When Application goes to background push the passcode viewcontroller to navigationcontroller in the delegate applicationDidEnterBackground because there will be that fractional flash almost all time u can have the passcodecontroller pushed before entering background.

Resources