Apple Binary Rejected (2.16) - ios

My app requires users current location to show him direction to a particular location in google map
Below is the code to show location on web view-
[self.getDirectionsWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude,self.projectLatitude,self.projectLongitude]]]];
The app declares support for location in .plist by using NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
Apple rejected the app with following reason
2.16 Details
Your app declares support for location in the UIBackgroundModes key in
your Info.plist file but still does not declare any features that
require persistent location. Apps that declare support for location in
the UIBackgroundModes key in your Info.plist file must have features
that require persistent location.
Specifically, we noticed that the Directions feature does not require
persistent location information, since it does not include
turn-by-turn navigation.
Any help will be appreciated, Thanks in Advance.

You just remove the location support from UIBackgroundModes key in info.plist
As you must only use UIBackgroundModes for location when you want to fetch location when your app is in background.
In your app declaration of NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription is enough.

Based on:
My app requires users current location to show him direction to a particular location in google map.
NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription
we noticed that the Directions feature does not require persistent location information, since it does not include turn-by-turn navigation
It looks like they're stating you shouldn't need location information unless the app is actually active. Since the location information is used to show the user the direction they need to head in, you should be able to simply adjust (with a little latency of course) when your app comes to the fore.
From Apple's documentation:
UIBackgroundModes (Array - iOS) specifies that the app provides specific background services and must be allowed to continue running while in the background.
These keys should be used sparingly and only by apps providing the indicated services. Where alternatives for running in the background exist, those alternatives should be used instead.
For example, apps can use the significant location change interface to receive location events instead of registering as a background location app.
That'd be my analysis though it's equally likely that the reviewer just had an argument with their significant other that morning, and is just being capricious :-) Nah, just joking, but it does sometimes seem to outsiders that the decisions they make are, shall we say, less than perfectly consistent.

It's is not necessary to request the background mode to request the user's current location.
I would recommend to use NSLocationWhenInUseUsageDescription if you don't need to use the user's location in background. Users are more inclined to deny the user location authorization when they see NSLocationAlwaysUsageDescription because they think that reduce the device's battery

Related

Request location updates permissions iOS

I currently have my app setup to request location services always, using [locationManager requestAlwaysAuthorization]; and NSLocationAlwaysUsageDescription
This works fine, however I would like to give the option of using location services only while using the app like in the screenshot below.
I have tried adding NSLocationWhenInUseUsageDescription however this overides he always request and only gives the alert for while in use, any ideas on who to give both options in settings?
First ask the user using your own dialog with two options - always / when using the app. Then call appropriate permission request according to the user's choice.
Either:
[locationManager requestAlwaysAuthorization];
or:
[locationManager requestWhenInUseAuthorization];
having both in plist is valid so that's not a problem. Depends on when you actually request it in the code.
It will be slightly tricky to maintain though, so a good code structure is crucial.
The built in iOS alert will only allows for one level of permission and it will only ask the user once. The assumption is that most apps will only need one or the other. In any case, if you want to have both options show up in the Settings, you must ask for Always permission.
More importantly though:
The Always setting is really only to be used by apps that require background location updates. So unless your app requires it, you shouldn't be asking for it. Also, using background location mode will cause your app to be more heavily scrutinized during the app review process.

beacon detection in background even though app is closed

Hi i am developing an application with beacons i need to scan for beacons continuously even though app is closed. is there any cordova plugin which is able to run in background, please suggest me sample applications tutorials
Background modes are only a partial answer. You need to have one of or both entries in Info.plist:
Then in some place in your code you need to ask for requestWhenInUseAuthorization or in your case requestAlwaysAuthorization. Then you need to handle this in location manager delegate. I'm doing it like so:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startMonitoringAllRegions];
[self.locationManager startUpdatingLocation];
}
else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
}
}
So somewhere i'm asking to start monitoring for a beacon region then in this method I'm checking if I have permission from the user to do that if not I'm requesting if (the string from the plist will be displayed) if I have I'm starting updating user location.
Hope that will get you going :D
This is possible with native iOS code, but not with Cordova. When you say "scan" beacons, this usually means using the CLLocation ranging APIs, which provid updates of all visible beacons every second. In order to do this continuously in the background, you need to:
Add location as a background mode in your app's .plist filke in XCode as #hasan83 suggests.
Start a background thread to keep your app running in the background.
Request requestAlwaysAuthorization as #sloik suggests.
I wrote a tutorial and reference app of how to do this. The tutorial mentions this working only for 3 minutes, but with the background mode of location, the 3 minute restriction goes away. Be aware that adding this background mode may make it more difficult to get your app approved for the AppStore. Apple must approve of the reasons for this background use of location services.
The reason you can't do this with Cordova is because JavaScript must run to collect the beacon data returned by the ranging APIs. This works in the foreground, but not in the background, because Cordova relies on a WebView being in the foreground to execute JavaScript code. In the background, your custom code just cannot run.
Allow UIBackgroundModes for location updates in the project plist
file.
Select the project at the left pane, then select Capabilities and expand the Background Modes list and select the Location updates option:
Try this plugin for using iBeacons. There seem to be a few plugins for keeping apps running in the background, e.g. this one. I doubt you'll find both functions in the same plugin.

Beacons and User Location permission

I just finished developing an app that interacts with the Beacons and User location.
I ask for locationManager the requestAlwaysAuthorization permission and I have added in the plist NSLocationAlwaysUsageDescription property with my description; everything works perfectly!!!
I realized that: if a user does not accept the requested permission, iOS disables localization always and when in use, making very limited the use of the app.
I wish that if a user refuses the requestAlwaysAuthorization automatically being asked requestWhenInUseAuthorization permission!
This is possible with some native method or I have to handle the request for another permission?
Thanks to all!
EDIT:
How do apps like Shazam or Facebook to have three choices "Never," "When in use" and "Always" in the location settings?
Surely there is a way to present them to the user?!?!
You can't do that. When in doubt, please always head to the Apple documentation.
https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestAlwaysAuthorization
After requestAlwaysAuthorization is finished (the user accepted/denied), the status is changed to ether kCLAuthorizationStatusDenied or kCLAuthorizationStatusAuthorized(or some other, doesn't matter).
Furthermore, both requestAlwaysAuthorization and requestWhenInUseAuthorization both have such logic (described in the documentation)
If the current authorization status is anything other than kCLAuthorizationStatusNotDetermined, this method does nothing and does not call the locationManager:didChangeAuthorizationStatus: method.`
If the user denies the requestAlwaysAuthorization the status is changed to kCLAuthorizationStatusDenied and both request authorizations will be ignored in future.

iOS App Rejected due to use of background location mode for geofence

Recently apple has rejected my app due to below reason.
Below is the explanation of functionality:
We require to track user entry and exit in the regions received from the server
If users enter in some defined region, We are also calling web-service and prepare the new set of geofence. We defined this type of fences as reset fence.
So it is also possible, Some time app is in background mode and user will might be enter in reset fence region so we require to call web-service and set up new fences in background.
We have used below flags of info.plist so app can run in background:
1 Required background modes:
App downloads content from the network
App registers for location updates
2 Required device capabilities:
armv7
Additional information:
App supports iOS 5.0 to iOS 8
Reason:
2.16: Multitasking Apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc.
----- 2.16 -----
We found that your app uses a background mode but does not include functionality that requires that mode to run persistently. This behavior is not in compliance with the App Store Review Guidelines.
We noticed your app declares support for location in the UIBackgroundModes key in your Info.plist but does not include features that require persistent location.
It would be appropriate to add features that require persistent use of real-time location updates while the app is in the background or remove the "location" setting from the UIBackgroundModes key. If your application does not require persistent, real-time location updates, we recommend using the significant-change location service or the region monitoring location service.
For more information on these options, please see the "Starting the Significant-Change Location Service" and "Monitoring Shape-Based Regions" sections in the Location Awareness Programming Guide.
If you choose to add features that use the Location Background Mode, please include the following battery use disclaimer in your Application Description:
"Continued use of GPS running in the background can dramatically decrease battery life."
Any one please suggest me that
In my case what info.plist settings i should use ?
What other changes i should check in the code. ?
Thanks in advance.
First of all you need to remove Location updates from the UIBackgroundModes.
Now, you need to write some code to handle what happens when the user enters a region. I wrote a very simplistic outline of a solution which detects when the user enters a region, sends that region's center to the web service (so it knows how to calculate the new regions) and monitors the new regions that are returned.
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
[self setNewFencesFromWebServiceAtCoordinates:[(CLCircularRegion *)region center] withCompletionBlock:^(NSArray *locations) {
int i = 0;
for (CLLocation * location in locations)
{
i++;
CLLocationCoordinate2D regionCenter = [location coordinate];
[manager startMonitoringForRegion:[[CLCircularRegion alloc] initWithCenter:regionCenter radius:100.0 identifier:[NSString stringWithFormat:#"location %d",i]]];
}
}];
}
- (void)setNewFencesFromWebServiceAtCoordinates:(CLLocationCoordinate2D)coordinates withCompletionBlock:(void(^)(NSArray * locations))completion
{
NSArray * newRegions;
// Write code to get the new regions from the web service and store them in an array of locations
completion(newRegions);
}

Android like permissions in iOS

In android, you define permissions for gps, sms sending, location , .., in the manifest file.
Is there anything similar in the iOS, so the user would know what capabilities of the phone some app uses before installation?
Or is the user warned during app use when some function wants to use something (e.g. gps, sms...)?
In iOS you declare your application requirements in its manifest-like Info.plist. But this information is not used to ask user permission, only for ensuring device compatibility.
Only Notifications and Location Services require user permission, which is automatically asked to the user the very first time your application attempt to use the corresponding API.
My guess is that many other permissions are already granted via the Apple Store license agreement, that the user must have accepted, unlike Android (I guess you can install an app without using the market isnt? which changes a lot from a legal point of view)
There's no such things as permissions on iPhone.
The only thing that user is warned about is when application uses his current location - then user is prompted with system alert and must explicitly allow or deny application's access to location data.
What concerns sms and email, they can be created and sent only via standard controllers so user will be aware of that anyway
on iOS you don't have to declare all necessary permissions in some specific file. You just use them. For example location
info.plist
//Privacy - Location When In Use Usage Description
<key>NSLocationUsageDescription</key>
<string>title</string>
//Privacy - Location Always and When In Use Usage Description
<key>NSLocationWhenInUseUsageDescription</key>
<string>description</string>
import CoreLocation
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
}
[IDFA]

Resources