Android Location Tracker with Google Maps

Last modified on March 15th, 2015 by Joe.

This Android tutorial will walk you through to create a location tracker using Android location API and Google maps services. This deals mainly with two areas, using the location API to continuously get the user location and then showing that lat-long position in the Google maps.

Refer the Android location using fused provider tutorial to understand better about the Android fused location provider API and how it can be used to access the user location. Next read through the, Markers–Google Maps Android API v2 to learn about showing a Google map and mark a location using latitude/longitude points.

Android-Location-Track-Google-Map

Prerequisite to user Google Maps API

  1. Create project in Google Console https://cloud.google.com/console/project
  2. Then go to menu “APIs & auth –> APIs” and switch on “Google Maps Android API v2”
  3. Create SHA1 Android key by running the following command in cmd prompt (you should have JDK installed and PATH setup).
    keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android 
    
  4. Grab the SHA1 value from the above cmd prompt and then go back to Google Console to create Android API key. Go to menu “APIs & auth –> Credentials” in ‘Public API access’ click create new Key button. Then used the SHA1 key generated and the android application package to create and get the Android API key.
  5. Add Google Play Services to project dependency. Just add the following in Gradle dependencies.
    compile 'com.google.android.gms:play-services:6.5.87'

Android Manifest for Location Tracker Example App

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javapapers.android.androidlocationmaps" >

    <permission
        android:name="com.javapapers.android.androidlocationmaps.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.javapapers.android.androidlocationmaps.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.javapapers.android.androidlocationmaps.LocationActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyARCTcX8baAnHL_ohscNcALAak-HnjTO5s" />

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
    </application>

</manifest>

Gradle Dependencies for Google Maps

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services:6.5.87'
    compile 'com.google.maps.android:android-maps-utils:0.3+'
}

I am using Android Studio to develop apps. Long back I have migrated from Eclipse to Android Studio. There are numerous advantages and I recommend you to move to Android Studio as quick as possible.

The last dependency in the Gradle is for ‘Google Maps Android API Utility Library’. I have used it to display the time as title in marker for Google maps. This is optional and you can ignore it without compromising the functionality.

Android Location Tracker Activity

package com.javapapers.android.androidlocationmaps;

import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.ui.IconGenerator;

import java.text.DateFormat;
import java.util.Date;

public class LocationActivity extends FragmentActivity implements
        LocationListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final String TAG = "LocationActivity";
    private static final long INTERVAL = 1000 * 60 * 1; //1 minute
    private static final long FASTEST_INTERVAL = 1000 * 60 * 1; // 1 minute
    Button btnFusedLocation;
    TextView tvLocation;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mCurrentLocation;
    String mLastUpdateTime;
    GoogleMap googleMap;

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate ...............................");
        //show error dialog if GoolglePlayServices not available
        if (!isGooglePlayServicesAvailable()) {
            finish();
        }
        createLocationRequest();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        setContentView(R.layout.activity_location_google_map);
        SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        googleMap = fm.getMap();
        googleMap.getUiSettings().setZoomControlsEnabled(true);
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart fired ..............");
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop fired ..............");
        mGoogleApiClient.disconnect();
        Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
    }

    private boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == status) {
            return true;
        } else {
            GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
            return false;
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
        startLocationUpdates();
    }

    protected void startLocationUpdates() {
        PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
        Log.d(TAG, "Location update started ..............: ");
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Connection failed: " + connectionResult.toString());
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d(TAG, "Firing onLocationChanged..............................................");
        mCurrentLocation = location;
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
        addMarker();
    }

    private void addMarker() {
        MarkerOptions options = new MarkerOptions();

        // following four lines requires 'Google Maps Android API Utility Library'
        // https://developers.google.com/maps/documentation/android/utility/
        // I have used this to display the time as title for location markers
        // you can safely comment the following four lines but for this info
        IconGenerator iconFactory = new IconGenerator(this);
        iconFactory.setStyle(IconGenerator.STYLE_PURPLE);
        options.icon(BitmapDescriptorFactory.fromBitmap(iconFactory.makeIcon(mLastUpdateTime)));
        options.anchor(iconFactory.getAnchorU(), iconFactory.getAnchorV());

        LatLng currentLatLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
        options.position(currentLatLng);
        Marker mapMarker = googleMap.addMarker(options);
        long atTime = mCurrentLocation.getTime();
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date(atTime));
        mapMarker.setTitle(mLastUpdateTime);
        Log.d(TAG, "Marker added.............................");
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng,
                13));
        Log.d(TAG, "Zoom done.............................");
    }

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

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);
        Log.d(TAG, "Location update stopped .......................");
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
            Log.d(TAG, "Location update resumed .....................");
        }
    }
}

I have configured the App to track the location every one minute. You can configure it in the constant INTERVAL and FASTEST_INTERVAL. Keep the INTERVAL higher and FASTEST_INTERVAL lesser or equal than that. For example, if you want to track location every five minutes then INTERVAL can be 1000 * 60 * 5 (five minutes) and FASTEST_INTERVAL can be 1000 * 60 (one minute). We are using Fused location provider API and internally it makes best judgment on which provider to use. INTERVAL does a real check using GPS or NETWORK_PROVIDER and that is a costly operation, it can drain the power. FASTEST_INTERVAL does gets location from other apps if available.

Location Google Maps Layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TaskRoadMap" >

    <fragment
        android:id="@+id/map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        class="com.google.android.gms.maps.SupportMapFragment"/>

</RelativeLayout>

Download

If you want to draw lines between the location points, refer the Draw lines on Google Maps Android API tutorial. We will get an innate feeling to draw path lines between the locations. But logically that is not right. We are finding only the location latitude and longitude points. We cannot predict the path the user has taken between those points. So its not appropriate to draw path between location points.

Comments on "Android Location Tracker with Google Maps"

  1. Hamid says:

    I have this issue and cannot run it:
    Error:(1, 0) Plugin with id ‘com.android.application’ not found.

  2. navneet says:

    Adb rejected connection to the client …..is displayed in ADB logs
    What should i do help me out??

  3. Isha says:

    I have resolved this problem by adding the below code in top level build file but in this project structure there is no such file so I just created new project and all done .

    But I m not getting anything in that map view now working on that.

    // *************************************************Top-level build file where you can add configuration options common to all sub-projects/modules.

    buildscript {
    repositories {
    jcenter()
    }
    dependencies {
    classpath ‘com.android.tools.build:gradle:1.2.3’

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    }
    }

    allprojects {
    repositories {
    jcenter()
    }
    }

  4. musa ray says:

    hai can you help me for i need to track multiple gps device in same time and there movement in same time

  5. Rehan Sarwar says:

    Hi ,Can you help me for i need to track the location of the person whose contact saved in my phone..

  6. Rehan Sarwar says:

    Hi i run this code with all the appropriate fixes but nothing is shown on my device..

  7. Anonymous says:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.maps/com.example.maps.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘com.google.android.gms.maps.UiSettings com.google.android.gms.maps.GoogleMap.getUiSettings()’ on a null object reference

  8. krishnareddy says:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.maps/com.example.maps.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘com.google.android.gms.maps.UiSettings com.google.android.gms.maps.GoogleMap.getUiSettings()’ on a null object reference

    am facing this error how to solve this please anyone thanks in advance

  9. srikanth says:

    hi,im trying to develop android app to find location of android device using mobile number can u please me

  10. srikanth says:

    can u please help me i need to display time and area at a time

  11. gowtham says:

    hai, i am new to android application so please tell where i get full explaination

Comments are closed for "Android Location Tracker with Google Maps".