Quantcast
Channel: ProgrammableWeb - Location
Viewing all articles
Browse latest Browse all 1090

Getting Started with LocationKit for iOS and Android

$
0
0
Thumbnail Graphic: 
Primary Target Audience: 
Primary Channel: 
Primary category: 
Secondary category: 
Related Companies: 
Related APIs: 
Apple Swift
Related Languages: 
Product: 

Many modern mobile apps rely heavily on GPS and user location data, whether it is part of an app's core functionality--such as with a navigation app--or is used more indirectly--such as for analytical and marketing purposes. There are few companies that can't benefit from contextual location user information, but it often comes at the cost of rapid battery degradation when using the default iOS or Android SDK location libraries. Enter SocialRadar's LocationKit, a direct replacement for these libraries that not only adds functionality but also reduces battery drain.

LocationKit will be a boon for companies that want to add location-based capabilities to their apps but don't have the development resources to build the features out themselves. As a direct replacement SDK, LocationKit inherits all of the features of CLLocationManager (iOS) and LocationManager (Android), but introduces a plethora of additional features.

Further, with its large database of venues, buildings and addresses, LocationKit saves on calls. After automatically detecting a significant place visit, it fetches all the contextual information:

let locationManager = LKLocationManager() locationManager.requestPlace() {(place: LKPlace?, error: NSError?) in
  if let place = place {
     print("The user is in: (\(place.locality))")
  }
}

Here are some of the most interesting and useful features in LocationKit:

Activity Modes

LocationKit can determine the current mode of activity the user is in--whether the user is walking, driving, at home or at work--by using raw data from sensors such as the GPS and accelerometer. The standard Apple and Android SDKs don't provide a sensory way of determining the mode the user is in. If your app has been authorized access to the iOS CoreMotion manager (which utilizes the motion coprocessor), LocationKit will switch over to using that instead of the raw sensors, This will save battery life and provide higher accuracy for activity mode tracking.

On iOS, you would listen for such activity as follows:

func locationManager(manager: LKLocationManager, willChangeActivityMode mode: LKActivityMode) {
  if (mode == LKActivityMode.Automotive) {
    print("The user is likely driving right now")
  } else {
    print("The user is likely NOT driving right now")
  }
}

People Nearby

The People Nearby feature makes it possible to detect other users of your app who are nearby. "Nearby" is a fluid term, according to LocationKit, but in general it refers to a city block. When an "LKPerson object" is returned, limited information about others users in range is made available. Enabling this feature in an app lets companies, for example, initiate marketing efforts or connect users.

LocationKit notes that user information is not shared with other users for security and privacy reasons. On iOS, developers would look for other nearby users, as follows:

locationManager.requestPeopleAtCurrentPlace { (people: [LKPerson]?, venue:LKVenue?, error:NSError) -> Void in
  if let people = people {
    print("There are \(people.count) people at \(venue.name) with you")
  } else {
    print("Sorry, no people found at \(venue.name) with you")
  }
}

Automatic Venue Detection

LocationKit can automatically detect when a user is at a venue, using Storefront Map Database. This visit monitoring capability detects when a user enters or leaves a particular place--say, Starbucks on 2nd and Market Street. LocationKit's SDK provides two delegate methods--didStartVisit and didEndVisit--to notify the system of those locational particulars:

func locationManager(manager: LKLocationManager, didStartVisit visit: LKVisit) {
  // Print out the street number and street name of the place where this
  // visit started
  print("Started visit at \(visit.place.subThoroughfare), \(visit.place.thoroughfare)")
}

There are many possible applications for this feature. For example, companies could use it to provide a promotion screen when a user enters a certain location--such as offering a 20% off coupon when a user enters a Starbucks between 3 p.m. an 5 p.m., or presenting a parking reservation ticket when a user enters a particular concert venue. This is accomplished regardless of whether the app is in the foreground or background, using a predictive algorithm that uses multiple sensors to pinpoint location. 

Android and iOS do provide standard geofencing capabilities, but LocationKit goes above and beyond by providing contextually aware place/venue information without extra reverse geocoding calls, while maintaining efficient battery-usage of the phone. image

Analytics Dashboard

LocationKit provides a robust dashboard through which a wide range of data is visualized.

For example, leveraging LocationKit’s ability to extrapolate key locations, business managers could see at a glance means when the app is being used at home and when it's used at work. you get to have a great graphical display of where your users live work, and shop. This, of course, improves companies' ability to improve “customer acquisition, app engagement and user retention."

Business managers can also have their dashboard broken down by segment--such as gender, age and income level--unlocking great customer insights without much work on the developer's part. In fact, that's the benefit of using LocationKit's analytics tool over any other popular tool, such as Google Analytics or Crashlytics: You are leveraging other LocationKit SDK features, so most of the coding effort has already been done. The only additional work developers need to do would be to pass custom event data to LocationKit's backend.

Slide12.jpgSlide41.jpg
As you can see, there are some real benefits to replacing your existing default Location Manager with something that can provide greater insight while not sacrificing performance and battery life. Next up, we will show you how easy it is to integrate LocatinKit into your iOS or Android app.

Getting Started with LocationKit SDK

Regardless of which platform you will work with, the first thing you need to do is sign up, after which you should receive your API token via the Developer Dashboard. The next steps are specific to each platform, so we will start with iOS.

iOS

The easiest way to get started on iOS, is with CocoaPods, adding the following to your Podfile:

pod 'LocationKit', '~> 3.0'

Then, check in Settings > Background Modes, that Location updates is enabled.
uezVNpFAQ7yByBK91FS2
Next, in your info.plist file, add the following privacy and permission-related attributes:

NSLocationAlwaysUsageDescription
Privacy - Location Usage Description

Finally, if you don’t have one already, create an objective-c bridging header, and add the following to reference the LocationKit Objective-C library:

#import <LocationKit/LocationKit.h>

To start using LocationKit in your app thereafter, you simply need to add the import statement to the top of your file:

import LocationKit

To start lKLocationManager immediately at launch, delegate file’s didFinishLaunchingWithOptions method, and add:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

  let locationManager = LKLocationManager()
  locationManager.debug = true //false if you are in production mode
  locationManager.apiToken = "YourToken"
  locationManager.startUpdatingLocation()

  return true
}

Getting a Location

The simplest way to get the current location is to use the requestLocation handler method:

self.locationManager.requestLocation { (location: CLLocation?, error: NSError?) -> Void in
    // We have to make sure the location is set, could be nil
    if let location = location {
        print("You are currently at: \(location)")
    }
}

Getting a Place

To get the current place--in a format other than latitude and longitude and without having to use iOS’s reverse geocoding--you can make use of LocationKit’s requestPlace method handler, to provide more contextual location information, such as a venue or place:

locationManager.requestPlace { (place: LKPlacemark?, error: NSError?) -> Void in
  if let place = place {
    print("Welcome to \(place)")
  } else if error != nil {
    print("Uh oh, got an error: \(error)")
  } else {
    print("Your current place couldn't be determined")
  }
}

There are of course a lot more features on iOS you can tap into so please...

Continued on page 2. 

Continued from page 1. 

...consult the advanced location features documentation section of LocationKit.

Android

Integration LocationKit into Android is just as easy, begining with setting up your build.gradle file:

repositories {
  mavenCentral()
  maven {
    url 'http://maven.socialradar.com/releases'
  }
}

dependencies {
  compile ('socialradar:locationkit:3.0.+@aar') { transitive = true }
}

You would then connect to the LocationKit service and receive location updates, by creating a location listener, as shown below:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
    private static final String API_KEY = "f0838784beb72a13";
    private static final String LOG_TAG = "MapsActivity";
    private static final String BUNDLE_KEY_LOCATION = "current_location";
    private GoogleMap mMap; // Might be null if Google Play services APK is not available.
    private Boolean mBound = false;
    private ILocationKitBinder mLocationKit;
    private Marker mMarker;
    private Location mCurrentLocation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        if (savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_KEY_LOCATION)) {

            mCurrentLocation = savedInstanceState.getParcelable(BUNDLE_KEY_LOCATION);
        }
     //   setUpMapIfNeeded();


    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
        Intent i = new Intent(this, LocationKitService.class);
        bindService(i, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (outState == null) {
            outState = new Bundle();
        }
        outState.putParcelable(BUNDLE_KEY_LOCATION, mCurrentLocation);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onPause() {
        disconnectIfNeeded();
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        disconnectIfNeeded();
        super.onDestroy();
    }
    private void disconnectIfNeeded() {
        if (mBound) {
            mBound = false;
            try {
                this.unbindService(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
     * installed) and the map has not already been instantiated.. This will ensure that we only ever
     * call {@link #setUpMap()} once when {@link #mMap} is not null.
     * <p/>
     * If it isn't installed {@link SupportMapFragment} (and
     * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
     * install/update the Google Play services APK on their device.
     * <p/>
     * A user can return to this FragmentActivity after following the prompt and correctly
     * installing/updating/enabling the Google Play services. Since the FragmentActivity may not
     * have been completely destroyed during this process (it is likely that it would only be
     * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this
     * method in {@link #onResume()} to guarantee that it will be called.
     */
    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
           ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMapAsync(this);

       }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        setUpMap();
    }

    /**
     * called by the onMapReady() if the mCurrentLocation is not set, it will pick a pint near africa. It will update when it gets a location
     */
    private void setUpMap() {
        if (mCurrentLocation != null) {
            mMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude())).title("Marker"));
        } else {
            mMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
        }
    }

    protected ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.v(LOG_TAG, "service connected");
            mBound = true;
            mLocationKit = (ILocationKitBinder) service;
            try {
                mLocationKit.startWithApiToken(API_KEY, mLocationListener);

                mLocationKit.getCurrentLocation(new ILocationKitCallback<Location>() {
                    @Override
                    public void onError(Exception e, String s) {
                        Log.e(LOG_TAG, s, e);
                    }

                    @Override
                    public void onReceivedData(Location location) {
                        Log.v(LOG_TAG, "got location");
                        if (mMarker != null) {
                            mMarker.setPosition(new LatLng(location.getLatitude(), location.getLongitude()));
                        }
                        if (mMap != null) {
                            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 19f);
                            mMap.moveCamera(update);
                        }
                        mCurrentLocation = location;
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mLocationKit = null;
            mBound = false;
            Log.v(LOG_TAG, "service disconnected");
        }
    };

    private String getPlaceName(LKPlace place) {

        if (place.getVenue() != null) {
            return place.getVenue().getName();
        } else if (place.getAddress() != null) {
            return String.format("%s %s", place.getAddress().getStreetNumber(), place.getAddress().getStreetName());
        }
        return "";
    }
    private ILocationKitEventListener mLocationListener = new ILocationKitEventListener() {
        @Override
        public void onStartVisit(LKVisit lkVisit) {
            Toast.makeText(MapsActivity.this, String.format("Start Visit: %s", getPlaceName(lkVisit.getPlace())), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onEndVisit(LKVisit lkVisit) {
            Toast.makeText(MapsActivity.this, String.format("End Visit: %s", getPlaceName(lkVisit.getPlace())), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onNetworkUnavailable() {

        }

        @Override
        public void onNetworkAvailable() {

        }

        @Override
        public void onLocationManagerDisabled() {

        }

        @Override
        public void onLocationManagerEnabled() {

        }

        @Override
        public void onChangedActivityMode(LKActivityMode lkActivityMode) {
            Toast.makeText(MapsActivity.this, String.format("Activity is %s", lkActivityMode), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onError(Exception e, String s) {

        }

        @Override
        public void onPermissionDenied(String s) {

        }

        @Override
        public void onUnbind() {

        }

        @Override
        public void onLocationChanged(Location location) {
            Toast.makeText(MapsActivity.this, String.format("Got Updated Location"), Toast.LENGTH_SHORT).show();
            if (mMarker != null) {
                mMarker.setPosition(new LatLng(location.getLatitude(), location.getLongitude()));
            }
            if (mMap != null) {
               CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 19f);
                mMap.moveCamera(update);
            }
            mCurrentLocation = location;
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };
}

For more information on working with the various operations and real-time information, refer to the LocationKit Android documentation.

Sample Code

For further help in getting started, there are links in the resources section, below, that will take you to sample Android and iOS sample projects.

Pricing

Pricing for  LocationKit is tiered and quite decent. Location Kit is free for startups; for more robust custom reporting and individua user analytics, the price jumps up to $995 per month.

Conclusion

LocationKit is virtually a drop-in replacement for your mobile device platform’s default standard location management services. This means that with very little effort you can develop apps that provide users with a more optimized experience, better battery performance and more accurate background tracking of user locations. The SDK further enriches the default functionalities by adding always-on location, automatic venue recognition, and access to place and venue databases from within the API (among many other features). LocationKit also provides a rich graphical dashboard to allow companies to analyze where users live, work and shop, offering the opportunity for greater contextual app engagements and more targeted demographic strategies.

Resources

Summary: 
In this article we take a look at the features of LocationKit, a replacement library for iOS’ CLLocationManager and Android’s LocationManager. We explain how LocationKit can benefit location-aware mobile apps, and take you through the process of setting up and using LocationKit in your own app.
Related Framework: 
LocationKit Java SDK by SocialRadar
Content type group: 
Articles

Viewing all articles
Browse latest Browse all 1090

Trending Articles