Android Location API can be used to track your mobile current location and show in the app. In this tutorial, we’ll develop an application that fetches the user’s current location programmatically.
There are two ways to get a users location in our application:
android.location.LocationListener
: This is a part of the Android API.com.google.android.gms.location.LocationListener
: This is present in the Google Play Services API. (We’ll look into this in the next tutorial)Android Location Services is available since Android API 1. Google officially recommends using Google Play Location Service APIs. Android Location Services API is still used to develop location-based apps for devices that don’t support Google Play Services.
The LocationListener interface, which is part of the Android Locations API is used for receiving notifications from the LocationManager when the location has changed. The LocationManager class provides access to the systems location services. The LocationListener class needs to implement the following methods.
The android.location
has two means of acquiring location data:
In this tutorial, we’ll create a Service that implements the LocationListener class to receive periodic location updates via GPS Providers or Network Providers.
The project consists of a MainActivity.java
class which displays a Get Location and a LocationTrack.java
Service class.
The activity_main.xml layout is defined below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.journaldev.gpslocationtracking.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn"
android:layout_centerInParent="true"
android:text="GET LOCATION" />
</RelativeLayout>
The MainActivity.java class is defined below.
package com.journaldev.gpslocationtracking;
import android.annotation.TargetApi;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.ArrayList;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
public class MainActivity extends AppCompatActivity {
private ArrayList permissionsToRequest;
private ArrayList permissionsRejected = new ArrayList();
private ArrayList permissions = new ArrayList();
private final static int ALL_PERMISSIONS_RESULT = 101;
LocationTrack locationTrack;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
permissions.add(ACCESS_FINE_LOCATION);
permissions.add(ACCESS_COARSE_LOCATION);
permissionsToRequest = findUnAskedPermissions(permissions);
//get the permissions we have asked for before but are not granted..
//we will store this in a global list to access later.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (permissionsToRequest.size() > 0)
requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]), ALL_PERMISSIONS_RESULT);
}
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
locationTrack = new LocationTrack(MainActivity.this);
if (locationTrack.canGetLocation()) {
double longitude = locationTrack.getLongitude();
double latitude = locationTrack.getLatitude();
Toast.makeText(getApplicationContext(), "Longitude:" + Double.toString(longitude) + "\nLatitude:" + Double.toString(latitude), Toast.LENGTH_SHORT).show();
} else {
locationTrack.showSettingsAlert();
}
}
});
}
private ArrayList findUnAskedPermissions(ArrayList wanted) {
ArrayList result = new ArrayList();
for (String perm : wanted) {
if (!hasPermission(perm)) {
result.add(perm);
}
}
return result;
}
private boolean hasPermission(String permission) {
if (canMakeSmores()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
}
}
return true;
}
private boolean canMakeSmores() {
return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case ALL_PERMISSIONS_RESULT:
for (String perms : permissionsToRequest) {
if (!hasPermission(perms)) {
permissionsRejected.add(perms);
}
}
if (permissionsRejected.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
showMessageOKCancel("These permissions are mandatory for the application. Please allow access.",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsRejected.toArray(new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT);
}
}
});
return;
}
}
}
break;
}
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
@Override
protected void onDestroy() {
super.onDestroy();
locationTrack.stopListener();
}
}
In the above code, we’re implementing runtime permissions that are used in Android 6.0+ devices. We’ve added the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in the AndroidManifest.xml file. Clicking the button invokes the LocationTrack.java service class. If the location returned is NULL in the case of GPS Provider, we call the showSettingsAlert()
method from the LocationTrack.java class that we’ll be seeing shortly. When the activity is destroyed stopLocationTrack()
method is called to turn off the location updates. The LocationTrack.java
class is defined below.
public class LocationTrack extends Service implements LocationListener {
private final Context mContext;
boolean checkGPS = false;
boolean checkNetwork = false;
boolean canGetLocation = false;
Location loc;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public LocationTrack(Context mContext) {
this.mContext = mContext;
getLocation();
}
private Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// get GPS status
checkGPS = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// get network provider status
checkNetwork = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!checkGPS && !checkNetwork) {
Toast.makeText(mContext, "No Service Provider is available", Toast.LENGTH_SHORT).show();
} else {
this.canGetLocation = true;
// if GPS Enabled get lat/long using GPS Services
if (checkGPS) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
}
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
}
}
/*if (checkNetwork) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
}
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (loc != null) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
}*/
}
} catch (Exception e) {
e.printStackTrace();
}
return loc;
}
public double getLongitude() {
if (loc != null) {
longitude = loc.getLongitude();
}
return longitude;
}
public double getLatitude() {
if (loc != null) {
latitude = loc.getLatitude();
}
return latitude;
}
public boolean canGetLocation() {
return this.canGetLocation;
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("GPS is not Enabled!");
alertDialog.setMessage("Do you want to turn on GPS?");
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
public void stopListener() {
if (locationManager != null) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.removeUpdates(LocationTrack.this);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
}
Few inferences drawn from the above code are:
In the above code isProviderEnabled(String provider)
is called upon the locationManager object and is used to check whether GPS/Network Provider is enabled or not.
If the Providers aren’t enabled we’re calling the method showSettingsAlert()
that shows a prompt to enable GPS.
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
method of the LocationManager class is used to register the current activity to be notified periodically by the named provider.
onLocationChanged
is invoked periodically based upon the minTime and minDistance, whichever comes first.
Location class hosts the latitude and longitude. To get the current location the following code snippet is used.
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
On the above Location object, getters are called to store the double values of latitude and longitude. These double values are then disabled as a Toast message on the screen.
To stop location updates removeUpdates method is called on the LocationManager instance.
The output of the above application in action on an emulator is: Our emulators can’t fetch locations, hence it’s returning 0.0 for lat/lng. You can connect your smartphone and run the application in debug mode to check your current location. To emulate GPS Locations in an emulator we can pass fixed Latitude and Longitude values from Android Studio. Besides the emulator window, you can see a list of options. The one at the bottom (which has three dots) is our Extended Controls options. Open that and send a dummy location. Your application should look like this: This brings an end to this tutorial. We’ll be implementing Location API using Google Play Services in a later tutorial. You can download the Android GPSLocationTracking Project from the link below.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This stuff works very fine for me. I add this into a timer instead of a button click, so that i can control when to get the location coordinates to be pass into google mapviewer in real time.
- amado tabasa
sir can i get android code for friends location logi/lati?
- satish
Youor code work but real device not show logiture/latiture?
- satish
What about the commented code? You are only using GPS service to get the location. For a real application, the commented lines should be uncommented and before the GPS part?
- Jaime
Hi, I’m always getting lat and lon 0.0, even on real devices. Any ideas with that?
- Sam Zhang
Hello sir.is there any program which pick the current address of user with latitude and longnitude.
- abdul moiz
In Android version 10 Location tracking not working and i am using transport tracker googleapi for getting the latlong to tracking the location. please kindly help me to resolve from this .
- pugazenthi
Hi Anupam Ur code was nice I want to get gps location automatically in time interval until I close r click a button like stop,and also is there a way to upload it to google sheets.
- Shyam
Hey Anupam Chugh, I’m getting lat 0.0,long 0.0 can you look into it.
- Chethan
java.lang.RuntimeException at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1013) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:562) at com.journaldev.gpslocationtracking.LocationTrack.getLocation(LocationTrack.java:82) at com.journaldev.gpslocationtracking.LocationTrack.(LocationTrack.java:48) at com.journaldev.gpslocationtracking.MainActivity$1.onClick(MainActivity.java:58) at android.view.View.performClick(View.java:6608) at android.view.View.performClickInternal(View.java:6585) at android.view.View.access$3100(View.java:782) at android.view.View$PerformClick.run(View.java:25945) at android.os.Handler.handleCallback(Handler.java:874) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:198) at android.app.ActivityThread.main(ActivityThread.java:6729) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
- Karthik