Why the app auto background refresh? - ios

if ([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusAvailable) {
NSLog(#"Background updates are available for the app.");
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied)
{
NSLog(#"The user explicitly disabled background behavior for this app or for the whole system.");
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted)
{
NSLog(#"Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user.");
}
And using this code to check the app status:
The app alway get into UIBackgroundRefreshStatusAvailable, and does not set any for "Background Modes" in capabilities(and info.plist).
Can anyone answer this, thanks.

The backgroundRefreshStatus property only mirror's device settings for the current user and is independent of the info.plist modes you set

Related

Show avaiable wifi connections nearby

Can I display the list of wifi access points on UI dialog & allow user to switch wifi settings from within my app by using swift 3?
OR
Is it possible to open the wifi settings on a prompt dialog which does not cover full screen?
No. Check this answer.
It may help you
Objective C
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"prefs:root=WIFI"]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=WIFI"]];
} else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"App-Prefs:root=WIFI"]];
}
Swift
if UIApplication.shared.canOpenURL(URL(string: "prefs:root=WIFI")) {
UIApplication.shared.openURL(URL(string: "prefs:root=WIFI"))
}
else {
UIApplication.shared.openURL(URL(string: "App-Prefs:root=WIFI"))
}

FCM/IOS, how to know if an user tapped on a notification alert or if we receive the notification directly?

on ios 9 and below, when an user click on a notification alert, it's fire the event applicationDidReceiveRemoteNotification but when the app is in foreground the notification arrive straight away to the app without showing any alert to the end user, and the event applicationDidReceiveRemoteNotification is also called :(
so how to know if the user click on a notification alert (maybe an old one) or if we receive the notification straight away because the app was in foreground ?
You can check the application states like this.
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) {
// Just received notification (Foreground)
} else if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateInactive) {
// launched by taping notification
} else if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
// Just received notification (Background)
}

Location Services not working in background called by WatchKit

My Apple Watch app requires some data and requests it from the corresponding iPhone app. To fulfill the request the iPhone app requires the users location.
After receiving and testing with a real Apple Watch I found out that my iPhone app does not receive location updates when running in background. If the iPhone app is active in foreground it works without issues. With the simulator it worked in both cases.
In both cases (active and background) the WatchKit extension calls and starts successfully the iPhone app and goes all the way until startUpdatingLocation is called in the iPhone app. But in case the app is running in background didUpdateLocations is never called.
I tried with requestAlwaysAuthorization as well as requestWhenInUseAuthorization. No difference.
I also activated then the "location updates" background mode within capabilities. But again no difference.
Has someone else faced the same problem and found a way to receive the location also in background?
Here some code. First the check if authorization is required.
// iOS 8 check to avoid crash on older iOS
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self requestLocationAlwaysAuthorization];
}
else
{
[self runLocationUpdate];
}
Here the check for the proper Location Manager rights.
- (void)requestLocationAlwaysAuthorization
{
CLAuthorizationStatus currentAuthStatus = [CLLocationManager authorizationStatus];
if (currentAuthStatus == kCLAuthorizationStatusDenied)
{
//request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusRestricted)
{
//request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusNotDetermined)
{
[self.locationManager requestAlwaysAuthorization];
[self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedWhenInUse)
{
//maybe when in use is also enough?
[self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedAlways)
{
//all ok
[self runLocationUpdate];
}
}
Here the call of startUpdatingLocation. The didUpdateLocations delegate will only be called when iPhone app is active.
-(void)runLocationUpdate
{
[self.locationManager startUpdatingLocation];
}
Three things to check and be aware of:
Location Permissions like [self.locationManager requestAlwaysAuthorization]; are only acknowledged once by the OS. If you have already requested permission, doesn't matter the level, the OS will NOT display a request to the user. The OS will just pass over the request and leave the permission level as is. The only time you can be assured that the OS will display the request to the user is if the [CLLocationManager authorizationStatus] returns kCLAuthorizationStatusNotDetermined. In every other case, you must manually request permission by displaying an Alert or other form of UI display. Also note that the OS retains whether or not it already displayed the request, even if you delete your app and reinstall it. So to test, you need to reset your Simulator's Content or your iPhone's Location Privacy.
Make sure you have added the plist keys for NSLocationAlwaysUsageDescription AND NSLocationWhenInUseUsageDescription If you don't add this to your plist, the OS will ignore any Location Permission Requests.
If you want to use requestAlwaysAuthorization to get location data from the phone (not the watch app extension) while the phone app is in the background, will also require you register for Background Modes Location updates under Project>Target>Capabilities.
UPDATE
Use a background task to give your app time to respond when in the background. Something like this:
-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:#"watchAppRequest" expirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//make your calls here to your tasks, when finished, send the reply then terminate the background task
//send reply back to watch
reply(replyInfo);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask=UIBackgroundTaskInvalid;
});
}

iOS: Programmatic way to tell whether or not push notifications are enabled

I have an iPhone development application with APNS enabled for the appID. In my applicationDidBecomeActive event I check to see whether or not push notifications are enabled by doing the following:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(#"applicationDidBecomeActive");
//Check if remote notifications are enabled for this app, if not proceed with performSetupAndWebService calls
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if(types == UIRemoteNotificationTypeNone)
{
//User has push notifications DISABLED for this application.
NSLog(#"PUSH NOTIFICATIONS DISABLED");
[self performSetupAndWebServiceCalls];
}
else
{
//User has push notifications ENABLED for this application.
NSLog(#"PUSH NOTIFICATIONS ENABLED");
NSLog(#"Registering for push notifications...");
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:(UIRemoteNotificationType)(UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert)];
}
}
It seems that no matter what I do, my code always tells me that push notifications are disabled. My app icon is in Notification Center in Settings and it is included. I have tried turning off specific types of notification and turning them back on but types == UIRemoteNotificationTypeNone is always true.
Am I missing something obvious? The bad thing is this seems to be affecting users of our production app as well, but not all of them. Very inconsistent and very frustrating.
Any advice?
When notifications are disabled and you try to register for them you get the following UIApplicationDelegate method called:
application:didFailToRegisterForRemoteNotificationsWithError:
- (BOOL) getpushNotificationstatus
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
return ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]);
}
else
{
UIRemoteNotificationType types = [[UIApplicationy sharedApplication] enabledRemoteNotificationTypes]; return (types & UIRemoteNotificationTypeAlert);
}
}
It will work in iOS8 as well

Push Notifications Permissions

Trying to work around a few corner cases for when push notifications are denied in the app and I have two questions:
1) Is there a way to reset whether the user has seen the notification request pop up?
2) Is there any way to determine if the user has said no to the notification request?
1) No, unless there's some private API that does that, but that's not allowed by Apple
2) The first time your app is started, after calling registerForRemoteNotificationTypes, you can check if didRegisterForRemoteNotificationsWithDeviceToken is called. If it's not, the user said "No thanks".
You can always check the status of the permissions if the user changes them, you can check them on applicationDidBecomeActive
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if ([[UIApplication sharedApplication] respondsToSelector:#selector(isRegisteredForRemoteNotifications)]) {
if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]){
NSLog(#"Notifications Enabled ios 8");
} else {
NSLog(#"Notifications not Enabled ios 8");
}
} else {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
{
NSLog(#"Notifications Enabled");
}
else
{
NSLog(#"Notifications not Enabled");
}
}
}
updated to make it work on iOS 8 too

Resources