Terminated App only being restarted one time - ios

I have an application that by design should be activated by the OS after a location event is delivered from the system even if the app has been terminated. Terminated can mean terminated by the system or by the user in the multitasking switcher. My app delegate code is below and the location delegate is an extension of the app delegate class. The first event that is generated by the system after the app is terminated is delivered to my app and processed properly, but I am not receiving any subsequent events. Is there some code I need to run after the event is received to reregister my application for future updates?
var window: UIWindow?
var locationManager: CLLocationManager!
var notificationCenter: UNUserNotificationCenter?
var today:String? //Today's date format: YYYY-MM-DD
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
self.locationManager = CLLocationManager()
self.locationManager.delegate = self
self.locationManager.requestAlwaysAuthorization()
self.locationManager.startMonitoringVisits()
self.locationManager.allowsBackgroundLocationUpdates = true
sendTestNotification()
} else {
print("normal launch")
}

You say your app has been "terminated". This suggests that you kill your app intentionally as a way of testing. But if an app has been forcibly terminated, the system deliberately stops background location monitoring, so naturally you won't get any more visit monitoring events. It is as if you had called stopMonitoringVisits yourself.

app terminate is not allow by apple as i know.
exit(0)
you can use that code line to app terminate

Related

how to make a IOS app with parse by AWS

all.
I want to make a IOS app with parse by AWS.
I watched [http://www.youtube.com/watch?v=sd2bphvVzGy][1]
this is Appdelegate.swift file.
import UIKit
import Parse
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let parseConfig = ParseClientConfiguration{ (ParseMutableClientConfiguration) in
ParseMutableClientConfiguration.applicationId = "myappid"
ParseMutableClientConfiguration.clientKey = "mymasterkey"
ParseMutableClientConfiguration.server = "http://ec2-13-124-93-153.ap-northeast-2.compute.amazonaws.com/parse"
// Override point for customization after application launch.
}
Parse.initialize(with: parseConfig)
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
I want to know how to get the information that "applicationId" and " Clientkey" from AWS. I cannot get the way to get the information at internet. anyone help me?
and if i run it.
there are wrong response.
2017-04-19 22:37:00.668 wanote[3667:493599] [Error]: unauthorized (Code: 0, Version: 1.12.0)
Optional(Error Domain=Parse Code=0 "unauthorized" UserInfo={error=unauthorized, NSLocalizedDescription=unauthorized, temporary=0})
Message from debugger: Terminated due to signal 15
could you teach me what is problem?
Best regards.

How to get incoming/outgoing call event in background state

In one of my app it has a feature of playing sound that I achieved successfully. Even though when app is running (foreground state) and we received the incoming call, app music gets stopped and resume again when call gets disconnected.
Now real problem is here. When app enters in the background state, we are not receiving any event for incoming/outgoing call. In the background mode If music is playing inside my app and we get any incoming call, then app music is stopped automatically but not resume again when call disconnected unlike iPhone Music app.
Is it a limitation of the iOS or can we achieve that ?
Note: I'm not looking for any solution for Jailbreak devices or Enterprise apps
Have you tried to create call center and assign handler block in AppDelegate class? The following has to work.
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let callCenter: CTCallCenter = CTCallCenter()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
callCenter.callEventHandler = {
(call: CTCall!) in
switch call.callState {
case CTCallStateConnected:
print("CTCallStateConnected")
case CTCallStateDisconnected:
print("CTCallStateDisconnected")
case CTCallStateIncoming:
print("CTCallStateIncoming")
default:
print("default")
}
}
return true
}
}
Do not forget to switch on Background Modes for this. And perform something in the background as well, smth like receiving location.

CLCircularRegion and wake up app

In application we have mechanism like native Reminder app in iOS with firing notifications when user enter or exit in some region.
But two devices behave differently (5 and 5s) in same time. All devices have enable notifications, and allow use locations.
Two devices have a some "travel" and in the route created 10 points. First device (5) when came to finish received only 6 notifications, (5s) don't receive any notification.
But my question is how I can know when my app is restart in background or continue working. Because, all log in app I redirect into a file, and after download container and analyze what happened in app in travel time.
I noticed app restart in same times when device is enter to region and my log marks fired in the file but notifications don't receive. This is happended when app try to get some information from web service in didFinishLaunchingWithOptions
And maybe this is problem. How to know distinguish restart app or continue working. Thx.
Are you checking UIApplicationLaunchOptionsLocationKey in didFinishLaunchingWithOptions similar to (sorry, Swift is what I have now):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsLocationKey] != nil {
// app was launched in response to incoming location event
}
}
Additionally, if you're not already doing this you may need to create notifications differently if app is in background:
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
}
else {
// Otherwise present a local notification:
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}

How can I make iOS background app notify based on location info

I am trying to implement a location-baed navigation app on iOS. I will have a device in my pocket and want it notifies when criteria are met based on location information, such as Google Maps navigation notifies when you make a turn on street.
I assume I can make it with CoreLocation and local notification.
Here are what I have done, expect and actually got.
XCode Version 7.1 (7B91b) on OS X El Capitan 10.11.1
In Xcode, File -> New -> Project -> iOS Application -> Single View Application
Add CoreLocation framework to project
Enable "Location updates" background mode
Add NSLocationAlwaysUsageDescription key with value of "hello" to info.plist
Leave ViewController.swift untouched
Edit AppDelegate.swift as follows;
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
lazy var locationManager: CLLocationManager! = {
let manager = CLLocationManager()
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.pausesLocationUpdatesAutomatically = false
manager.delegate = self
manager.requestAlwaysAuthorization()
return manager
}()
var lastNotifictionDate = NSDate()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let settings = UIUserNotificationSettings(forTypes: [.Alert], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
locationManager.startUpdatingLocation()
return true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Do something interesting.
// I make this function return immediately until 10sec passed after previous notification.
let now = NSDate()
if lastNotifictionDate.dateByAddingTimeInterval(10).compare(now) == .OrderedDescending {
//NSLog("Not yet")
return
}
//NSLog("It's time")
lastNotifictionDate = now
// Fire local notification, without sound configured for simplicity.
let notification = UILocalNotification()
notification.alertBody = "Hello"
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}
// ... other methods are untouched ...
}
The app works on simulator as I expect, namely;
Run the app in iPhone 5 Simulator and allow location and notification services
Press home button (Shift-Command-H).
In the simulator menu, Debug -> Location -> Free drive
The app displays a local notification alert every 10sec
The app acts different on my device, iPhone 5 with iOS 9.1;
Run the app via Xcode and allow location and notification services
Pressed home button
The device does not display notification alert either on home screen or notification center.
Then, I tap the app icon on the device to bring the app foreground, opened the notification center and found two notifications. I expect 5 notifications newly appear if I wait for 50 seconds, but no notification newly appear.
I understand Simulator behaves differently than the actual devices. For example, Simulator shows NSLog() and print() outputs on console during background, while the actual device does not.
I guess I did not configure something for devices or I am trying to do in unfeasible way, but I cannot find what it is. Could you please tell me what is wrong and how I can fix it?
Setting CLLocationManager's allowsBackgroundLocationUpdates to true solved my problem.
manager.allowBackgroundLocationupdates = true
If it is false (default), updates stops when suspended. Updates occur when foreground or background.

Check if iOS push notifications status is not determined

I’m prompting my user to enable push notifications after the user logs in to my app. I know how to test if push notifications are enabled or disabled using:
isRegisteredForRemoteNotifications
and it works just fine. It returns YES for enabled and NO for not available but I want to be able to figure out how to check for Not Determined (the user wasn’t prompted to enable push notifications to begin with). Is there a way to test that?
Thanks in advance!
You create Not Determined state yourself.
func registerNotification() {
// 1.Call register API
// ...
// 2.Save a bool value to indicate you've called this method or not.
let appleSuggestedUserDefaultsKeyPrefix = "com.yourcompany.product-"
let key = appleSuggestedUserDefaultsKeyPrefix + "didCallRegisterNotificationAPI"
NSUserDefaults.standardUserDefaults().setBool(true, forKey: key)
}
And in didFinishLaunchingWithOptions method you need check if you have called registerNotification().
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let didCallRegisterNotificationAPI = NSUserDefaults.standardUserDefaults().boolForKey(...)
if didCallRegisterNotificationAPI {
// If registered or user denied, call this method will NOT show the alert.
// Just the same as you did before.
registerNotification()
} else {
print("registerNotification() has not been called")
}
}
And finally you can call registerNotification() directly anywhere anytime as you need and the alert is under your control now.
isRegisteredForRemoteNotifications is a Bool. There is no undetermined status. You can verify this is the reference.
When the user first installs your app they must either allow or disallow push notifications. There is no other possible option.
However, maybe you're asking because you can delete the app, reinstall, and it won't ask you for permission. That's because the permission is remembered.
Resetting the Push Notifications Permissions Alert on iOS
The first time a push-enabled app registers for push notifications, iOS asks the user if they wish to receive notifications for that app. Once the user has responded to this alert it is not presented again unless the device is restored or the app has been uninstalled for at least a day.
If you want to simulate a first-time run of your app, you can leave the app uninstalled for a day. You can achieve the latter without actually waiting a day by following these steps:
Delete your app from the device.
Turn the device off completely and turn it back on.
Go to Settings > General > Date & Time and set the date ahead a day or more.
Turn the device off completely again and turn it back on.
Reference
Associated Question: When I delete my iOS application push notification state remains
EDIT:
You can only use isRegisteredForRemoteNotifications to check that they are simply not registered, whether that's due to declining or due to you never trying to register.
However, as long as you try to register in a valid way (valid certs and profiles etc) and the user declines, your app will call did register, but with nil UIUserNotificationSettings:
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types == nil {
println("You didn't allow notifcations")
}
}
You can make use of UNNotificationSettings's authorizationStatus property.
private func checkNotificationsAuthorizationStatus() {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.getNotificationSettings { notificationSettings in
switch notificationSettings.authorizationStatus {
case .authorized:
print("Authorized to schedule or receive notifications.")
case .denied:
print("Not authorized to schedule or receive notifications.")
case .notDetermined:
print("Not determined whether the app is allowed to schedule notifications.")
case .provisional: // Available from iOS 12.0
print("Provisionally authorized to post noninterruptive user notifications.")
#unknown default:
print("Error")
}
}
}
Use it in didFinishLaunchingWithOptions like:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.registerForRemoteNotifications()
self.checkNotificationsAuthorizationStatus()
return true
}

Resources