Detect iPhone device capabilities for Core Location - iphone

I have a core location app that I'm writing leveraging the startMonitoringSignificantLocationChanges method to generate updates when appropriate but this does not work on older devices such as iPhone 3g.
I would like for the core location functionality to still work while the device is open, so I thought I could use a selector test to see if the device supports the method, and if it doesnt just use the standard core location updating method. Although this selector doesnt work on my iphone 3g, it still uses startMonitoringSignificantLocationChanges even though it doesnt work on the phone.
Any ideas? I would rather not use the device identifier tests because then it will have to be updated for every future release of the phone.
#interface RootViewController : UITableViewController <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property (nonatomic, retain) CLLocationManager *locationManager;
#implementation RootViewController
#synthesize locationManager;
if([locationManager respondsToSelector:#selector(startMonitoringSignificantLocationChanges)]) {
[locationManager startMonitoringSignificantLocationChanges];
NSLog(#"Using bg updates");
}
else {
[locationManager startUpdatingLocation];
NSLog(#"Using reg updates");
}

if ([CLLocationManager significantLocationChangeMonitoringAvailable]) {
…
}

Related

How to use geo-based push notifications on iOS?

Is it possible to make use of geo-based push notifications on iOS when the application is killed (not in the background)?
I am interested in building an app, where the user will choose a position on a map, and then if he/she for example is close to that area a local geo-based push notification would be triggered.
However is this "idea" even possible? Can the GPS run and compare coordinates when the app is killed and run and notify the user when is in place? Is there a tutorial/article/more information of any kind on the subject that i could read?
Most of the information I read online were more like general ideas of implementing without anything specific though on the matter.
For tracking a user's location while the app is not running (ie. has previously been terminated), there are two options:
From the iOS app programming guide under "Tracking the User's Location":
The significant-change location service is highly recommended for apps that do not need high-precision location data. With this service, location updates are generated only when the user’s location changes significantly; thus, it is ideal for social apps or apps that provide the user with noncritical, location-relevant information. If the app is suspended when an update occurs, the system wakes it up in the background to handle the update. If the app starts this service and is then terminated, the system relaunches the app automatically when a new location becomes available. This service is available in iOS 4 and later, and it is available only on devices that contain a cellular radio.
However, according to the CLLocationManager class reference, it's not too accurate and updates are infrequent:
Note: Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
Region Monitoring works in a similar way - including restarting the app after being terminated - but with higher accuracy (depending on availability of Wifi networks and cell towers):
The specific threshold distances are determined by the hardware and the location technologies that are currently available. For example, if Wi-Fi is disabled, region monitoring is significantly less accurate. However, for testing purposes, you can assume that the minimum distance is approximately 200 meters.
Another region monitoring consideration is that (according to the CLLocationManager class reference) region entry and exit notifications might only be received 3-5 minutes or so after crossing the region's boundaries.
Depending on the actual requirements, region monitoring could be used for obtaining a "rough" location and then when the user is within a specific region, start up the more accurate GPS based service on the location manager. When the user leaves the region of interest, turn off the GPS service to preserve battery and revert to the rough location monitoring service (ie. region monitoring) once again. Here's a basic implementation:
SomeViewController.m:
...
#interface SomeViewController () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLRegion *someRegion;
#end
#implementation SomeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
CLLocationDistance radius = 10; // 10 metre sensitivity
self.someRegion = [[CLRegion alloc] initCircularRegionWithCenter:someCoordinates radius:radius identifier:#"Smithtown Dry Cleaners"];
self.locationManager.delegate = self;
[self.locationManager startMonitoringForRegion:self.someRegion];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 10;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
[self.locationManager stopUpdatingLocation];
}
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* location = [locations lastObject];
// If the user's current location is not within the region anymore, stop updating
if ([self.someRegion containsCoordinate:location.coordinate] == NO) {
[self.locationManager stopUpdatingLocation];
}
NSString *locationData = [NSString stringWithFormat:#"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude];
NSLog(#"%#", locationData);
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = locationData;
localNotification.alertAction = #"Location data received";
localNotification.hasAction = YES;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
Remember to add the appropriate entries to the application's plist file so the app will run in the background with access to the appropriate resources:
MyApp-Info.plist:
<key>UIBackgroundModes</key>
<array>
...
<string>location</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
...
<string>location-services</string>
<string>gps</string>
</array>
The above code assumes the use of iOS6 and ARC

Animation not working on iPad. same works on iphone

I've got a very simple project that tries to animate a UIView using block based iOS4.0 animation.
header
#interface animatepadViewController : UIViewController {
UIView *contentView;
}
#property(nonatomic, retain) IBOutlet UIView *contentView;
#end
implementation
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[UIView animateWithDuration:1.0 animations:^{self.contentView.alpha = 0.0;}];
}
I've added a subview of type UIVIew in the interface builder with a background color of black.
these are the only change i've made from the default ipad "view" based project.
I get the following error
2010-12-28 17:59:05.689 animatepad[29835:207] *** +[UIView animateWithDuration:animations:]: unrecognized selector sent to class 0x217689c
this happens only on the ipad and NOT on the iPhone
thanks in advance
Have you updated your iPad to use iOS 4.2 yet? Blocks weren't available on the iPad's shipping version of iOS (3.2.)
To update the simulator, you will need to update Xcode to version 3.2.5.

iPhone: Why does applicationMusicPlayer quit playing when app enters background?

I made a little test app to try to isolate this issue, but it exhibits the same behavior: the applicationMusicPlayer stops playing immediately when the app enters the background. I don't know what I'm doing wrong, or if it's an Apple bug. It seems so simple that if it were an Apple bug others would have encountered it and posted on it.
I've set the info.plist UIBackgroundModes key to Audio
I've verified that the app is not terminating
I've tested on 4.1 beta 3 with the same results
I've searched the web for similar complaints. People report other MPMediaPlayerController issues/bugs, but more complex e.g. involving interaction with AVAudio.
Any/all suggestions appreciated.
Here's the core of my test app:
MPTest.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MediaPlayer/MediaPlayer.h>
#interface MPTestViewController : UIViewController <MPMediaPickerControllerDelegate> {
MPMusicPlayerController *MPPlayer;
}
#property (nonatomic, retain) MPMusicPlayerController *MPPlayer;
#end
MPTest.m
#import "MPTestViewController.h"
#implementation MPTestViewController
#synthesize MPPlayer;
- (void)viewDidLoad {
[super viewDidLoad];
// get the application music player
self.MPPlayer = [MPMusicPlayerController applicationMusicPlayer];
// break to allow application didFinishLaunching to complete
[self performSelector:#selector(presentMPPicker) withObject:nil afterDelay:0.01];
}
- (void)presentMPPicker {
// present the picker in a modal view controller
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
picker.delegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
// delegate called after user picks a media item
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
[self dismissModalViewControllerAnimated:YES];
// tell the player what to play
[MPPlayer setQueueWithItemCollection:mediaItemCollection];
// start playing
[MPPlayer play];
}
#end
MPMusicPlayerController does not support background audio. You will need to use something like AVAudioPlayer or AVPlayer (AVPlayer allows you to use iPod libary items via the AssetURL).
The reason is that MPMusicPlayerController uses the iPod application to play audio, thus your application is not actually playing anything.
Please see this thread on the Apple Developer Forums for more information: https://devforums.apple.com/thread/47905?start=0&tstart=120
Did you set the appropriate audio session type for being a media player? The OS uses session types to make decisions among competing uses for the audio channels.

how to show current location on MKMapView

I am using MKMapView on my application. i need to show current location on simulator.
is it possible. to show current location on simulator.
In the simulator, the user's current location is always in Cupertino, California.
If you're using Interface Builder to add your map view, simply check the "Shows User Location" check box in the Attributes Inspector for the map view. (Select the map view and type command-1 to display the attributes inspector.)
If you're adding or manipulating the map view programmatically, set the showsUserLocation property of the map view to YES.
Update: It turns out that this is possible, just not using the built in map view functionality, and it doesn't always work.
Recent versions of the SDK (which have to run on Snow Leopard) can get the location of the machine the simulator is running on using CLLocationManager. You can then use this location to create an annotation to display on the map view. It won't behave like the built in "user's location indicator" (at least not without some work), but it will show the user's current location.
See this post for details of when this technique won't work.
See the "Related sample code" section of the CLLocationManager documentation for sample code that uses CLLocationManager and CLLocationManagerDelegate and then displays the user's location on a map view.
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
This will show the current location in MkMapview.
If you are using Interface Builder,In the Attributes Inspector , we have an option Behaviour which has an option Show User Location, on checking that option will also do the same.
If you are not able to see in simulator,
Open the application in the simulator.
From the Menu Bar select Debug - > Location - > (If "None" option is selected ,change it to "Custom Location") and set location .
With CLLocationManager also we can get the current location,
Import Corelocation FrameWork to the project
In .h file
#import <CoreLocation/CoreLocation.h>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation* currentLocation;
In .m file
if ([CLLocationManager locationServicesEnabled] )
{
if (self.locationManager == nil )
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kDistanceFilter; //kCLDistanceFilterNone// kDistanceFilter;
}
[self.locationManager startUpdatingLocation];
}
The delegate function :
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
self.currentLocation = [locations lastObject];
// here we get the current location
}
Hope this answer may help you.
Simulator will not show user current location no matter whether it is iOS 6, 6.1 or iOS 7. To simulate location you can see here. If you want to show user current location then run your app in device or change simulator setting -
from the simulator's menu choose Debug > Location > Custom Location....

(iPhone) how to implement draggable pins using OS 4.0 MapKit?

Can anyone provide any sample code/instructions for implementing draggable pins in OS 4.0 using the MapKit framework?
Sure thing buddy (yes I'm talking to myself),
In your custom annotation add:
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
This satisfies the requirement of implementing setCoordinate, as mentioned inhttp://developer.apple.com/iphone/library/documentation/MapKit/Reference/MKAnnotationView_Class/Reference/Reference.html#//apple_ref/occ/instp/MKAnnotationView/draggable
In your MapView delegate add:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState
{
//..Whatever you want to happen when the dragging starts or stops
}
and in your AnnotationView set draggable to true, so for example:
customAnnotationView.draggable = YES;
I think that was everything that I did to get it working. Tell me if you have troubles.
Check out MapKitDragAndDrop by Ching-Lang Huang and the author's accompanying blog post.