How programmatically restart an iPhone app in iOS - ios

How programmatically restart an iPhone app in iOS?
I find this way http://writeitstudios.com/david/?p=54
But may be something simple.

The only way I know to do this is not ideal, but it works.
First, your app has to opt out of background execution (multitasking) The app has to quit when exited, not run as a background task. This is done with the plist key UIApplicationExitsOnSuspend.
Second, your app needs to register a custom URL scheme that can be used to launch the app.
Third, you need a web page hosted somewhere that when loaded will redirect to your app's custom URL scheme.
Forth, the user needs an active Internet connection.
To exit and restart, call UIApplication openURL on your hosted redirecting web page. Your app will exit and safari will launch and load your page. The page will redirect Safari to your custom URL scheme, prompting Safari to internally call openURL, causing iOS to launch your app.

my post that you linked to is referring to a Cocoa Application, not the iOS. On the iOS, you can quit an application (but Apple doesn't like this) by using exit(0); but I don't recommend that. You cannot restart iPhone apps though.

Unless you're developing for jailbroken devices, Apple won't even allow you to programatically terminate your app. So restarting the device is out of the question.

Your AppDelegate instance has a method
(void)applicationDidBecomeActive:(UIApplication *)application
{
}
In here, you can put logic to figure out if the app should restart, or continue doing whatever it was doing. For example you can have a BOOL variable appMustRestart that is false at first but gets triggered as true whenever something happens in your app that you'd like the next time to be a fresh relaunch.
if (appMustRestart)
{
[self resetVars]; // call a method that resets all your vars to initial settings
// INSERT CODE HERE TO TRANSFER FOCUS TO INITIAL VIEWCONTROLLER
}

Related

How to check application state under swift UI Test

Some background
I am currently writing a UI Test for a settings pane, and click on buttons to enable certain permissions such as push notifications and location services.
However, if the alert for the permission has been displayed before (regardless of the user allowing or denying access to the permission), the alert will not display again, and will just take the user to the settings app. Unfortunately, these settings do not reset, meaning the first time I run the UI tests, alerts will show; and on all subsequent UI test runs, the buttons will take me to the settings app unless I reset the device before the tests begin.
My issue
Thus, my test needs to know if the app went into the background, and attempt to foreground it to continue the testing:
if app.state == background {
foregroundApp()
}
// continue with other tests
Is there any way to determine if the app is in the background?
What I tried
I researched methods to determine the state of the application (running/background/etc) from a UI test, and was not able to find much. I tried to check whether certain elements exist:
if (app.navigationBars.element.exists) ...
but this gives me runtime errors[1] if the user is taken to the settings page because the app under test is in the background, and the test cannot lookup the navigationBars (or other elements).
I tried using some of the methods from Facebook's private headers for XCUIApplication() and XCUIElement().
XCUIApplication().state always returns 3 no matter what state the app is currently in, and any attempts to call XCUIApplication().resolve() to foreground the app give me the same errors as before[1]
I tried to rewrite the logic to foreground the app before resuming the tests, but methods such as XCUIApplication().launch() kill the app before restarting, which I cannot do. Only siri service seems to work for me, but I cannot access the siri service through the corporate proxy, and modifying proxy permissions is not possible.
Is there any other way to check the app state?
Errors
[1] This error is printed every time I try to do something involving state. I do not call snapshotView anywhere, and thus the suggestion to use afterScreenUpdates is useless.
Failure to get snapshot within 15.0s
Cannot snapshot view (<UIKeyboardImpl: 0x7febcc75d000; frame = (0 0;
414 226); layer = <CALayer: 0x608000625720>>) with
afterScreenUpdates:NO, because the view is not in a window. Use
afterScreenUpdates:YES.`
tl;dr
I need to check whether the app I am UI testing has entered the background (i.e. user pressed the home button). Checking for existence of particular elements such as navigation bars doesn't work, neither do most methods from Facebook's private headers for XCUIApplication/XCUIElement. Foregrounding the app also causes issues, and relaunching the app is not an option; neither is siri service.
You can do this in Swift 4, using XCUIApplication.state, which will give you information about the state of the app - whether it's in the foreground or background etc. however, it's not possible to find this information in Swift 3 and below. Essentially, UI testing in Swift 3 doesn't support leaving the app.

Ios 8: Determine the destination app when my app goes to the background?

I override my app's openURL-method to know when we're about to leave the app from an ABPersonViewController, the reason being that that class doesn't notify its delegate on all of the actions it presents to the user. If it did everything would be fine.
This worked flawlessly in iOS 7, but when trying this in iOS 8.1 it turns out that the ABPersonViewController doesn't call openURL for all its actions anymore. For instance, tapping a phone number gets me to the phone app without calling openURL. Tapping the SMS bubble on the other hand will call openURL.
When tapping the facebook profile entry (with the URL "fb://profile/1234567890") the log says that "Launch Services" doesn't have a registered handler for the scheme "fb". So I'm assuming that calls to Launch Services have replaced the calls to openURL. I can't find out much more about it other than that it's "a private API".
Is there a way to detect these calls? Or, is it possible to override handlers for known schemes like "tel" and "mailto" internally for my app? I basically just need to know when we're leaving the app and where we're going.

terminating an app from didFinishLaunchingWithOptions

So, I have an app that monitors significant location changes. I want to only record changes at most every 2 hours. The other times, I really don't want my app to startup at all. Does anyone know if I can terminate my app from within
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Will returning "False" cause my app not to be loaded (from the docs it seems that is only if it is trying to handle a URL).
You should not terminate the app as it lead to rejection by apple.As docs say
There is no API provided for gracefully terminating an iOS application.
You can show pop up to user for appropriate message.During development or testing you can call abort().But you should not ship your app with any of terminate api as apple strongly discourage this.
you can try exit(0); but Let me warn you apple may reject your app if you terminate your app willingly, what would be better is to show a dialogue box containing the reason and asking the user to close the app on thier own.
You really should not terminate your application, but should prompt the user that there's nothing to show at the moment and have them go to the home screen.
However, if you really want to, you can use abort().
From Apple's Developer Library (emphasis added):
In iOS, the user presses the Home button to close applications. Should your application have conditions in which it cannot provide its intended function, the recommended approach is to display an alert for the user that indicates the nature of the problem and possible actions the user could take — turning on WiFi, enabling Location Services, etc. Allow the user to terminate the application at their own discretion.
[...]
If during development or testing it is necessary to terminate your application, the abort function, or assert macro is recommended.

How know if iOS device is sleeping in a background process

I have a application running in background and I need to know if device is sleeping in order to start a sincronisation process, but I didn't find information about this.
Does anyone know if it is posible and how do it?
Thanks.
You cannot know if the device is asleep because you have no control over the OS.
You can, otherwise, use the App Delegate method:
- (void)applicationWillResignActive:(UIApplication *)application
{
//your code goes here
}
if you want to wait till your app goes to background
I believe you can't do this using public API. The only thing which you can check whether your application is active or in background (using AppDelegate callbacks). And as Luke pointed out in comments, checking whether device "falls asleep" isn't iOS best design practice.
There are some private API's to do what you want, you can look at following questions:
Is there a way to check if the iOS device is locked/unlocked?
Detect screen on/off from iOS service
However, you should be aware that your app won't be accepted in AppStore in such case.

Close the app in 'applicationDidEnterBackground'

I have an iOS app and for several reasons I need to close it when the user clicks the home button of the device. I can't support background.
I now there is an option called Application does not run in background, but I can't use it because there is a bug from Facebook sdk that makes impossible to authenticate with Facebook when this option is in use. Here is the bug report at Facebook.
So I don't know what to do, how can I restart it? An [[NSThread mainThread] exit] in applicationDidEnterBackground?
Is there a workaround for this?
The legal (Apple will approve the app) way is set or create the key UIApplicationExitsOnSuspend to YES in the Info.plist.
To get this as action you would need exit(0) or [[NSThread mainThread] exit], but this is against the Human Interface Guidelines from Apple
So what you could also do is just design all your views in a manner that they have a reset function . Then when applicationDidEnterBackground store that you need to reset on next startup or directly call reset on all active views in applicationWillEnterBackground
So your App didn't really restart, but all your views look like this. To give you an advice, I would design my app in a manner that it doesn't shutdown itself when i quit. This is no good user experience.. Once clicked the home button and all your data is away, same when you receive a call.
Plain old stdlib.h exit() will terminate the app, though it violates apple guidelines (see "Don't Quit Programmatically").
Your app won't perform any background actions if you don't initiate any.

Resources