Location Services will not activate on iPad - ios

I am developing an iOS app which uses Location Services. The app works fine on iPhones (3GS and 4), but does not request locations services when run on the iPad. That is, the user is never asked to enable location services, nor does the app appear in Location Services section of the Settings app.
I have seen a few forum posts describing similar issues, but all of these were resolved by installing the app on the iPad through iTunes (via ad-hoc distribution) rather than running it through Xcode, or by resetting location warnings. I tried both of these solutions on an iPad, an iPad 2, and the iPad simulator, both to no avail.
We use the following code to enable Location Services updates. We have verified both by on-device debugging and placement of NSLogs that our code is getting run.
- (id)init {
[super init];
if (clManager == nil) {
clManager = [[CLLocationManager alloc] init];
}
clManager.delegate = self;
[self startLocationMonitoring];
return self;
}
- (BOOL)isLocationAvailable {
return [CLLocationManager significantLocationChangeMonitoringAvailable];
}
- (void)startLocationMonitoring {
if ([self isLocationAvailable]) {
[clManager startMonitoringSignificantLocationChanges];
} else {
// handle lack of Location Services
}
}

This probably does not answer your question, but might help somebody. The WiFi iPad models don’t support significant location changes (the significantLocationChangeMonitoringAvailable method returns NO) and the startMonitoringSignificantLocationChanges seems to do nothing when running on these – it does not trigger the error delegate method nor it brings forward the blue bubble dialog asking for location services permission.

iPad comes in 2 models (wifi and wifi+3G). http://www.apple.com/ipad/specs/
The wifi model does not have A-GPS support.
If yo go through the specification you will see that A-GPS is only available on wifi+3G model and perhaps you are using the wifi(only) model.
However, through WIFI, iPad can detect locations if router is providing the same which does not seems to be in your case.
You can try your app on iPad2 wifi+3G version and you will see that it runs just fine..!!

Related

iOS 10 - WLAN Access Setting Doesn't Appear In Some iOS Devices

Our app is using WLAN to communicate with a wireless device. When our app is installed in iOS 10. Sometimes, udp socket doesn't work. The reason for that is, in iOS 10 they added a new setting or permission under your app that allows the user to switch on or off the user of WLAN or cellular data.
The following would appear in the settings of the app:
When I tap on the Wireless... It will bring me to this UI:
After allowing WLAN use. The app would work fine.
Now, the problem is, sometimes, or in some devices running iOS 10, the settings that I just showed you doesn't appear(I am referring to the setting shown on the first image). So, is there anything I can do to make that settings always appear? It seems that sometimes iOS system doesn't recognize that my app is using wireless data. And it would result in my app would never get to use WLAN forever.
There is no user permission to use WIFI in iOS10.
The application in your screenshot (BSW SMART KIT) is using Wireless Accessories (WAC), i.e. is able to connect to wireless speakers. To accomplish this the Wireless Accessory Configuration capability is required. This is what you can dis/enable in the systems settings (your screenshot).
The switch in the settings shows up after connecting to a device via WIFI through WAC. You can see this behaviour in your sample app (BSW SMART KIT) too.
This sample code might let you get the idea. Detailed information in Apples documentation.
After a time of researching. I ended up seeking help with Apple Code Level Support. Apple states that this problem would most probably occur when you reskin your app. They say that probably it's because of the Image UUID of the main app and the reskinned app are the same. When you install both of them in your phone, the system will treat the reskinned app as the same app compared to the main app. So, if the one app fails to access WLAN, then it will also affect the other one. According to them, this appears to be a bug in iOS. And currently, they don't have any solution for the developers. This is the radar bug number:
What I did to somehow lessen the occurrence of the problem is to add tracking to the Network Restriction by using the following code.
- (void)startCheckingNetworkRestriction
{
__weak AppDelegate *weakSelf = self;
_monitor = [[CTCellularData alloc] init];
_monitor.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
NSString * statusStr;
switch(state)
{
case kCTCellularDataRestrictedStateUnknown:
{
statusStr = #"restriction status:Unknown";
}
break;
case kCTCellularDataRestricted:
{
statusStr = #"restriction status:restricted";
[weakSelf performUrlSession];
}
break;
case kCTCellularDataNotRestricted:
{
statusStr = #"restriction status:not restricted";
}
break;
default:
{
abort();
}
break;
}
NSLog(#"Restriction state: %#", statusStr);
}];
};
}
Take note that you have to import CoreTelephony to do this.
#import CoreTelephony;
when I detect that the network is restricted. I will open a URL session to force internet access attempt and would hope that the restriction alert dialog would pop out. Once the alert is pop out, then the WLAN Access Settings that I was talking about would definitely appear under the settings. There are times that this doesn't work. If it happens, then you'll just have to rename the bundle ID, and make a couple of changes to your code and then rebuild it a couple of times (Well, that's what I did when I was experimenting this). Reinstalling the app won't do a thing. Restarting and resetting the phone won't do either.
Hope this helps.

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.

iOS7 and iOS 8 location services

I have an app and I want to add some location based features to it. It supports both iOS 7 and 8, but I'm having some issues.
I want to request the permission for location only when the user taps a certain button on a certain viewController. The issue is that the permission request appears as soon as the app launches. To be more precise, between ViewWillAppear and ViewDidAppear functions of the first viewController.
What I have tried previously:
having the NSLocationWhenInUseUsageDescription key in the plist (for iOS8).
In terms of code:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
Removing the plist key -> this caused the pop up in iOS8 not to appear anymore, but it still does in iOS7
At the moment every single bit of code related to CoreLocation is commented out and I still do get the dialog asking me for permissions (iOS7 only)
I don't know what else I could possibly try, so any bit of help is much appreciated
That's just how iOS 7 (and before) works. You're not in charge of the authorization dialog: the system is. You can't make it appear; the system, seeing that you are using Core Location, presents it on your behalf. That is exactly the sort of thing that iOS 8 changes. All you can do in iOS 7 is look to see whether location services are turned on and whether your app is authorized.
Ok, I discovered the issue.
It turns out that a third party app is requesting permissions as soon as the app opens.
Thank you for all the answers.

How to stop using the Location Services within my iOS app?

I have an iOS app that uses the CLLocationManager to monitor regions and to get GPS updates. Most of the time, I want my app to continue tracking the cellphone when it goes in background or even when it gets killed, and it works well (I can still see the small arrow in the status bar after my app gets killed). The problem is that I am not able to stop monitoring the regions and GPS updates after my app has been restarted by the Location Services.
When my app gets restarted by the Location Services, I instanciate the CLLocationManager and then call its methods stopRangingBeaconsInRegion and stopUpdatingLocation before setting its delegate to nil and itself to nil.
Thanks to NSLogger, I can see that my callbacks are no longer called, but the small arrow in the status bar stays there (and my app is the only one that I allowed to use the Location Services from the settings menu).
What did I miss? Is there a way to know what still uses the Location Services in my app?
When you call stopRangingBeaconsInRegion, where are you getting the list of regions? The proper way to do this is like below:
for (CLRegion *monitored in [self.locationManager monitoredRegions]) {
NSLog(#"Stopping monitoring on: %#", monitored.identifier);
[self.monitoringLocationManager stopMonitoringForRegion:monitored];
}
for (CLBeaconRegion *region in [self.locationManager rangedRegions]) {
NSLog(#"Stopping ranging on: %# ", region.identifier);
[self.rangingLocationManager stopRangingBeaconsInRegion:region];
}
I finally found that I missed to remove some of my numerous regions. The easy way to avoid this mistake is to retrieve the list of regions monitored with the property monitoredRegions and call stopRangingBeaconsInRegion for each of them. I also forgot to call stopMonitoringSignificantLocationChanges (I didn't know that my app was using it, since I am modifying the app of a former colleague).
How do you know that it is your app that is using the location services?
The small arrow appears if the iOS itself is using the location services in the background.
if you did call stopRangingBeaconsInRegion and stopUpdatingLocation before setting the delegate to nil and you are not getting any callbacks then your app is not using the location services.

ios deferred location updates fail to defer

I am looking into using deferred location updates for an iOS activity tracker, which allows location services in background. I've implemented the suggested code snippets (see below). In Xcode debugging, deferred locations attempt to start a few times until location data comes in at about 1 per second. After that, it claims to succeed in starting deferrals, and the callback for the finish trigger also succeeds after the specified time period expires. However during the time, the location handler still runs once per second. I've read that this is because the phone hasn't deemed itself ready to enter the background, and that testing in Xcode does this. Note, AppDelegate's "didEnterBackground" eventhandler got called immediately when turning off the screen, and resumed when reopening app.
I ran the same code with the phone disconnected as another test, near the window with GPS, screen off, or switching to entirely different apps, and it still never actually defers the updates. I can tell because the networked update still comes in once every 30 seconds, instead of the interval of 120 seconds which is desired in the code sample below.
What else is needed to actually get deferrals to work, since there is no error occurring in starting them and they do get their finish callback? Why do location updates continue at 1 per second even when the app goes to background?
Iphone 5s, IOS 7.1.1
// .h file (partial)
#interface MotionTracker : NSObject<CLLocationManagerDelegate, UIAccelerometerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
// .m file (parial)
- (id) init {
if(self = [super init]){
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// if set to YES (default), app stops logging location at some point and doesn't resume in any timely fashion, all data points lost in between
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeFitness;
}
return self;
}
// called early in program after login confirmed
- (void) startCollectingLocation {
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// logs to file when device is not in debug
// always returns 1
NSLog(#"Location update count: %d",[locations count]);
// some code here to handle location updates
// - collect key location day in NSDictionary
// - every N seconds send Network call to server to save (have tried 30 seconds, 15 minutes, 30 minute network intervals). Have also tried turning off network calls completely.
// deferred updates starter
if (!self.deferringUpdates) {
if([CLLocationManager deferredLocationUpdatesAvailable]){
[_locationManager allowDeferredLocationUpdatesUntilTraveled:500 timeout:(NSTimeInterval)120]; // (have also tried large numbers, and "Infinite"
self.deferringUpdates = YES;
NSLog(#"Deferred updates start");
} else {
NSLog(#"Deferred updates not available");
}
}
}
- (void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
if(!error){
_deferringUpdates = NO;
NSLog(#"Deferred updates: finished");
} else {
_deferringUpdates = NO;
NSLog(#"Deferred updates: %#", [error localizedDescription]);
}
}
If the device is connected to a debugger or on a charger, the device will remain powered (not sleep) and therefore will not enter deferred mode. Deferred mode is a power optimization allowing the device to sleep. If the device is not scheduled to sleep for other reasons, enabling deferred mode will not force it to sleep otherwise. Try your test by ensuring no other apps are using location services, and disconnecting it from a charger with the screen off. After running for some time, plug back in and check your logs, you should see that the device slept and deferred updates.
From Apple's
allowDeferredLocationUpdatesUntilTraveled:timeout: documentation:
Deferred updates are delivered only when the system enters a low power
state. Deferred updates do not occur during debugging because Xcode
prevents your app from sleeping and thus prevents the system from
entering that low power state.
It is also worth noting that deferred updates are only available when locationManager.desiredAccuracy is set to kCLLocationAccuracyBest OR kCLLocationAccuracyBest; locationManager.distanceFilter must also be set to kCLDistanceFilterNone.
From Apple's documentation:
...the location manager allows deferred updates only when GPS hardware is available on the device and when the desired accuracy is set to kCLLocationAccuracyBest or kCLLocationAccuracyBestForNavigation.
and
...the distanceFilter property of the location manager must be set to kCLDistanceFilterNone.
I have been struggling with the same issue, and I may have found an answer that solves this problem for many - at least it solves my problem and gets deferred updates working consistently for me.
I followed all of the steps in this list and no matter what I did, location updates would not defer. It occurred to me that I might have other apps running that were not allowing the system to sleep, so I killed all other apps in the multitasking tray. I ran my sample app again and ... it worked!
But the story doesn't end there. I tried again a little later, and even though there were no other apps running in the multitasking tray I couldn't get location services to defer. Then it occurred to me that I have an app on my phone called "Moves" which manages to keep itself alive even after you manually kill it. I'm not entirely sure how Moves comes magically back to life when you kill it, but it does (perhaps using bluetooth and the app preservation / restoration service). Even though it is alive and tracking your location it doesn't appear in the multitasking tray. I think that only apps that are manually launched appear in the tray - if the OS launches an app it doesn't appear in the tray. But I digress ...
I was able to get deferred location services to work consistently in my app by disallowing Moves to use location services. When I did, Moves complained even though it wasn't in multitasking tray. It seems that if another app is using location services (and not deferring) your app won't defer either.
Hi recently with the iOS 9 GM seed version out,I have seen location update(allowDeferredLocationUpdatesUntilTraveled:timeout:) not getting deferred.The same code used to work in iOS 8.4 and below versions.Its draining my device's battery by a huge margin.
Is there anything we need to explicitly set or mention for iOS 9?Didn't find anything from Apple documentation
Here is the code that I implemented.
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (!self.deferringUpdates) {
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:30];
self.deferringUpdates = YES;
} }
-(void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error { // Stop deferring updates self.deferringUpdates = NO;
}
I also set the allowsBackgroundLocationUpdates property but even that didn't help. self.locationManager.allowsBackgroundLocationUpdates=YES;
In iOS 9 and later, regardless of deployment target, you must also set the allowsBackgroundLocationUpdatesproperty of the location manager object to YES in order to receive background location updates. By default, this property is NO, and it should remain this way until a time when your app actively requires background location updates.
https://developer.apple.com/library/prerelease/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html
Please let me know what additional I need to make
Thanks

Resources