Google Maps iOS SDK, Getting Current Location of user - ios

For my iOS app (building in iOS7),i need to show user's current location when the app load.I am using Google Maps iOS SDK. I am following this
Google Map
But i can't figure it out. Please help if you go through the path.

Forget my previous answer. It works well if you use the native MapKit.framework.
In fact GoogleMaps for iOS do all the work for you. You don't have to use CoreLocation directly.
The only thing you have to do is to add yourMapView.myLocationEnabled = YES; and the framework will do everything. (Except center the map on you position).
What I have done : I simply followed the steps of the following documentation. And I got a map centered on Sydney but if I zoomed out and moved to my place (if you use a real device, otherwise use simulator tools to center on Apple's location), I could see the blue point on my position.
Now if you want to update the map to follow your position, you can copy Google example MyLocationViewController.m that is included in the framework directory. They just add a observer on the myLocation property to update the camera properties:
#implementation MyLocationViewController {
GMSMapView *mapView_;
BOOL firstLocationUpdate_;
}
- (void)viewDidLoad {
[super viewDidLoad];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868
longitude:151.2086
zoom:12];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView_.settings.compassButton = YES;
mapView_.settings.myLocationButton = YES;
// Listen to the myLocation property of GMSMapView.
[mapView_ addObserver:self
forKeyPath:#"myLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
self.view = mapView_;
// Ask for My Location data after the map has already been added to the UI.
dispatch_async(dispatch_get_main_queue(), ^{
mapView_.myLocationEnabled = YES;
});
}
- (void)dealloc {
[mapView_ removeObserver:self
forKeyPath:#"myLocation"
context:NULL];
}
#pragma mark - KVO updates
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (!firstLocationUpdate_) {
// If the first location update has not yet been recieved, then jump to that
// location.
firstLocationUpdate_ = YES;
CLLocation *location = [change objectForKey:NSKeyValueChangeNewKey];
mapView_.camera = [GMSCameraPosition cameraWithTarget:location.coordinate
zoom:14];
}
}
#end
With the doc I gave you and the samples included in the framework you should be able to do what you want.

It seems Google Maps iOS SDKcannot access to the device position.
So you have to retrieve the position by using CLLocationManagerof iOS.
First, add the CoreLocation.framework to your project :
Go in Project Navigator
Select your project
Click on the tab Build Phases
Add the CoreLocation.framework in the Link Binary with Libraries
Then all you need to do is to follow the basic exemple of Apple documentation.
Create a CLLocationManager probably in your ViewDidLoad:
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
//Configure Accuracy depending on your needs, default is kCLLocationAccuracyBest
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500; // meters
[locationManager startUpdatingLocation];
With the CLLocationManagerDelegate every time the position is updated, you can update the user position on your Google Maps :
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power.
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// Update your marker on your map using location.coordinate.latitude
//and location.coordinate.longitude);
}
}

Xcode + Swift + Google Maps iOS
Step by step recipe:
1.) Add key string to Info.plist (open as source code):
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs your location to function properly</string>
2.) Add CLLocationManagerDelegate to your view controller class:
class MapViewController: UIViewController, CLLocationManagerDelegate {
...
}
3.) Add CLLocationManager into your class:
var mLocationManager = CLLocationManager()
var mDidFindMyLocation = false
4.) Ask for permission and add observer:
override func viewDidLoad() {
super.viewDidLoad()
mLocationManager.delegate = self
mLocationManager.requestWhenInUseAuthorization()
yourMapView.addObserver(self, forKeyPath: "myLocation", options: NSKeyValueObservingOptions.new, context: nil)
...
}
5.) Wait for authorization and enable location in Google Maps:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.authorizedWhenInUse) {
yourMapView.isMyLocationEnabled = true
}
}
6.) Add observable for change of location:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if (!mDidFindMyLocation) {
let myLocation: CLLocation = change![NSKeyValueChangeKey.newKey] as! CLLocation
// do whatever you want here with the location
yourMapView.camera = GMSCameraPosition.camera(withTarget: myLocation.coordinate, zoom: 10.0)
yourMapView.settings.myLocationButton = true
mDidFindMyLocation = true
print("found location!")
}
}
That's it!

On any iOS device, get the user's location with Core Location. Specifically, you want the CLLocation class (and CLLocationManager).

Is delegate method didTapMyLocationButton is not way?
https://developers.google.com/maps/documentation/ios/reference/protocol_g_m_s_map_view_delegate-p#ac0e0171b811e839d9021800ca9fd33f4
- (BOOL)didTapMyLocationButtonForMapView:(GMSMapView *)mapView {
return YES;
}
And you can get location by
(lldb) po mapView.myLocation
<+37.33243033,-122.03088128> +/- 386.93m (speed -1.00 mps / course -1.00) # 5/19/14, 6:22:28 PM Moscow Standard Time

The current location won't show on the simulator... connect a real device and give it a try
I spent 2 days running in the simulator and don't know that it doesn't simulate locations

there are many methods...
I used this method and it works in all cases. Google gives you everything with the reponse in json format and its on you how you deal with that data.
Some steps are there to load google map in your project.
find the api key from this link https://developers.google.com/places/ios-api/
sign in with your google account and add your project and create a ios key.
then use this in your project
enable all the api needed for google map
a-googlemaps sdk for ios
b-googlemap direction api
c-" " javasripts api
d- picker api
e- places api for ios
f distance matrix api
in appdelegate method...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:#"xxxxxxxx4rilCeZeUhPORXWNJVpUoxxxxxxxx"];
return YES;
}
add all needed library and frameworks in your project
if google map is not working it means you have to add required framework
all the best play with google map

Related

Get GPS coordinates of moving marker on Google Maps iOS

I need to pick coordinates of current marker position on Google maps. It should update coordinates as marker is moving on map.
I'm using GoogleMaps , GooglePlaces and GooglePlacePicker API's. I can get nearby places using GooglePlacePicker API but I want to pick exact coordinates of location where marker is present.
It is already done in Uber?
Use this,
.h
#interface ViewController : UIViewController <CLLocationManagerDelegate> {
GMSMapView *mapView_;
GMSMarker *marker_;
float currentLatitude;
float currentLongitude;
}
#property(nonatomic,retain) CLLocationManager *locationManager;
#property (nonatomic)CLLocationCoordinate2D coordinate;
.m
- (void)viewDidLoad {
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if (IS_OS_8_OR_LATER) {
if ([_locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[_locationManager requestWhenInUseAuthorization];
}
}
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(#"%#",locations);
CLLocation *currentLoc=[locations objectAtIndex:0];
NSLog(#"CurrentLoc : %#",currentLoc);
_coordinate=currentLoc.coordinate;
currentLatitude = currentLoc.coordinate.latitude;
currentLongitude = currentLoc.coordinate.longitude;
}
-(void)plotMarkerForLatitude:(float)latitude andLongitude:(float)longitude {
// Now create maker on current location
if (marker_ == NULL) {
marker_ = [[GMSMarker alloc] init];
}
CLLocationCoordinate2D target =
CLLocationCoordinate2DMake(latitude, longitude);
marker_.position = target;
marker_.title = #"title";
marker_.appearAnimation = kGMSMarkerAnimationPop;
NSLog(#"%f %f",latitude,longitude);
marker_.icon = [UIImage imageNamed:#"marker"];
marker_.snippet = #"Address";
marker_.map = mapView_;
}
In Plist :
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow access to get your current location</string>
This can possibly be done by implementing the GMSMapViewDelegate protocol. See the guide to events and the list of methods on the GMSMapViewDelegate.
As mentioned in the documentation,
Applications can use this event to trigger a refresh of markers or other content being displayed on the GMSMapView, rather than, for example, reloading the content on every camera change.
You may also check Google Maps SDK for iOS for more information on what other APIs you can use along with Maps iOS SDK to build location-relevant apps and sites.

Retrieving location on the Apple Watch

I want to get the latitude and longitude of the user and display it on the Apple Watch.
I have already included the core location framework in my Watchkit Extension.
When I run the program all I get for the lat and long is 0.0 and 0.0
I tested the same method in a class on the iPhone and it worked, and gave me the appropriate coordinates. What am I doing wrong?
The .h file:
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface InterfaceController : WKInterfaceController
#end
The .m file:
#import "InterfaceController.h"
#interface InterfaceController()
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
- (IBAction)showLocation {
NSString * geoLoc = [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
NSLog(geoLoc);
}
#end
Before you can get any location updates to your watch app extension you will need to authorize location updates in your iPhone app. If you haven't authorized location updates in your iPhone app, then your watch extension will not get any location updates. Also, I am pretty sure you need to set the permission to always allow for location updates [CLLocationManager requestAlwaysAuthorization]. I don't think it will work if you use [CLLocationManager requestWhenInUseAuthorization], though I am not 100% sure about the permissions.
In Xcode, you want use the Debug menu to simulate a location that's either pre-set or use a GPX file as the location source.
In the CLLocationMananager documentation, the location property states
The value of this property is nil if no location data has ever been retrieved.
That means that you need to call [self.locationManager startUpdatingLocation] in order to get a valid location. But there a could things you need to do before that will work.
First of all you will need to request authorization by calling [self.locationManager requestAlwaysAuthorization].
When authorization is approved or declined, the delegate method locationManager:didChangeAuthorizationStatus: will be called.
If the authorization status is kCLAuthorizationStatusAuthorizedAlways than you can call [self.locationManager startUpdatingLocation].
Then anytime the location is updated, the delegate method
locationManager:didUpdateLocations: will be called so you can update your UI with the new location.
You are not supposed to request location data within a WatchKit Extension.
From Apple Watch Human Interface Guidelines:
“Avoid using technologies that request user permission, like Core
Location. Using the technology from your WatchKit extension could
involve displaying an unexpected prompt on the user’s iPhone the first
time you make the request. Worse, it could happen at a time when the
iPhone is in the user’s pocket and not visible.”
I am using this code
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
{
[locationManager requestAlwaysAuthorization];
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
and to display in wkinterfaceMap i use this code
CLLocationCoordinate2D mapLocation = CLLocationCoordinate2DMake([latitude floatValue],[longitude floatValue]);
//
MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(1, 1);
[self.mapkit addAnnotation:mapLocation withPinColor: WKInterfaceMapPinColorPurple];
[self.mapkit setRegion:(MKCoordinateRegionMake(mapLocation, coordinateSpan))];

Using freeway drive/ city run in iOS simulator in background mode

I am trying to make use of the options within iOS simulator : debug->freeway drive/ city run in order to simulate the location updates.
In my code I am using CLLocationManager for getting location updates with following code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDistanceFilter:20];
}
-(void)viewWillAppear:(BOOL)animated {
[locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)lm didUpdateLocations:(NSArray *)locations{
CLLocation *location = [locations lastObject];
NSLog(#"Location returned: %f, %f Accuracy: %f", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy);
}
I am never getting a callback on the delegate for location updates, while my app is in background and i am selecting the option in simulator.
I have provided my app the background mode for location updates. Please let me know how exactly to use these features or if i am missing anything here.
I finally sorted out the problem. The simulator's options are working perfectly fine but it was the implementation of CLLocation which was the problem.
On iOS 8 the location update code will not work unless :
You add NSLocationWhenInUseUsageDescription & NSLocationAlwaysUsageDescription to the plist with some string values that will be prompted to user.
You need to add ask user's permission for getting the location codes to work:
[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]
Taken from this post.

AFNetworking and CLLocation Manager iOS

My question is as follows:
When is the location updated when using Location Services? When I called startUpdatingLocation I expected to already have a location returned so I can retrieve latitude and longitude for my iOS project. These are required parameters for a web service as well but it seems they are returned as nil.
The interface conforms to CLLocationManagerDelegate protocol and I have implemented the methods for it. Anyway here is my code:
- (void)viewDidLoad
{
super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
if([self.parentViewController isKindOfClass:[BTMainViewController class]])
{
BTMainViewController *parent = (BTMainViewController *)self.parentViewController;
self.sessionKey = parent.session;
NSLog(#"URL is %# ", self.sessionKey);
}
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// also set the URL
self.serviceURL = [apiURL stringByAppendingString:#"/get_employee_closestlocations"];
// set tableview delegate and data source
self.tableView.delegate = self;
self.tableView.dataSource = self;
// adjust for EdgeInset with navigation bar.
self.tableView.contentInset = UIEdgeInsetsMake(64.0f, 0.0f, 0.0f, 0.0f);
// fetch the locations here
[locationManager startUpdatingLocation];
[self fetchLocations];
}
didUpdateToLocation implementation
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = [locationManager location];
[locationManager stopUpdatingLocation];
if(currentLocation != nil)
{
[self setLongitude:[NSNumber numberWithDouble: currentLocation.coordinate.longitude]];
[self setLatitude:[NSNumber numberWithDouble: currentLocation.coordinate.latitude]];
}
}
Any suggestions would be welcome and thanks in advance!
The delegate method you are using is deprecated. You should use locationManager:didUpdateLocations: and then access the location update from the end of the array -
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *currentLocation = (CLLocation *)[locations lastObject];
...
}
It can take some time to get a location fix, particularly as you have specified kCLLocationAccuracyBest - iOS may need to start up the GPS receiver if it hasn't been used recently and then the GPS needs to obtain a fix - if the device is inside or has bad GPS reception this can further delay the acquisition of a location. You can get an idea of the time to obtain a fix by restarting your device, starting the maps application and tapping the location "arrow" and waiting until the blue location circle collapses down to the blue & white marker.
I would suggest that you invoke your [self fetchLocations]; from the didUpdateLocations method
Also, the Core Location documentation states -
When requesting high-accuracy location data, the initial event
delivered by the location service may not have the accuracy you
requested. The location service delivers the initial event as quickly
as possible. It then continues to determine the location with the
accuracy you requested and delivers additional events, as necessary,
when that data is available.
So, there is a risk that when you do access the location, it may not be particularly accurate. You can look at the horizontalAccuracy property of the CLLocation and decide whether you want to accept this location or wait for a more accurate location (bearing in mind that it may not arrive if the device is inside or has poor reception)
You need to do in viewDidLoad like this
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
mapView.delegate = self;
mapView.showsUserLocation = YES; // Enable it when we want to track user's current location.
}
after doing this the below delegate method will automatically called.
- (void)mapView:(MKMapView *)mapView
didUpdateUserLocation:
(MKUserLocation *)userLocation
{
self.mapView.centerCoordinate = userLocation.location.coordinate;
}

GMSMapView myLocation not giving actual location

I have a GMSMapView properly loaded and working inside my viewcontroller
what i'm not being able to do is setting the GMSCameraPosition around my location
this is my code:
mapView_.myLocationEnabled = YES;
CLLocation* myLoc = [mapView_ myLocation];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:myLoc.coordinate.latitude
longitude:myLoc.coordinate.longitude
zoom:4];
[mapView_ setCamera:camera];
GPS is enabled and application has all needed permissions but myLocation returns a nil CLLocation, consequentially cameraWithLatitude:longitude:zoom: get 0 0 coordinates and displays Africa instead of my actual location (that is not in africa :) )
From official Google Maps iOS SDK documentation:
(BOOL) myLocationEnabled [read, write, assign]
Controls whether the My Location dot and accuracy circle is enabled.
Defaults to NO.
(CLLocation*) myLocation [read, assign]
If My Location is enabled, reveals where the user location dot is being drawn.
If it is disabled, or it is enabled but no location data is available, this will be nil. This property is observable using KVO.
So when you set mapView_.myLocationEnabled = YES;, it only tells the mapView to reveal the blue dot only if you have a location value given to the myLocation property. The sample code from Google shows how to observe the user location using the KVO method.(Recommended) You can also implement the CLLocationManagerDelegate method, to update the mapView.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[mapView animateToLocation:newLocation.coordinate];
// some code...
}
Here are the code from google maps sample code on how to use KVO to update user location.
// in viewDidLoad method...
// Listen to the myLocation property of GMSMapView.
[mapView_ addObserver:self
forKeyPath:#"myLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
// Ask for My Location data after the map has already been added to the UI.
dispatch_async(dispatch_get_main_queue(), ^{
mapView_.myLocationEnabled = YES;
});
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (!firstLocationUpdate_) {
// If the first location update has not yet been recieved, then jump to that
// location.
firstLocationUpdate_ = YES;
CLLocation *location = [change objectForKey:NSKeyValueChangeNewKey];
mapView_.camera = [GMSCameraPosition cameraWithTarget:location.coordinate
zoom:14];
}
}
Try to using MapKit, under the VieDidLoad or ViewWillApper using:
myMapView.showsUserLocation = YES;
You can add this simple code under the IBAction if you want, like a :
- (IBAction)getLocation:(id)sender{
myMapView.showsUserLocation = YES;
}
I hope this help you

Resources