In this tutorial, we will learn how to get the user’s location coordinates – Latitude, Longitude and Altitude by building a simple Android Application that will use the LocationManager class.
Contents
What is LocationManager?
This class provides access to the device’s location services. These services allow the applications to obtain periodic updates of the device’s geographical location, or to be notified when the device enters the proximity of a given geographical location. This class helps to leverage the location capabilities of the user’s Android device.
To use this class, we first need to obtain some permissions from the user. These are:
- Manifest.permission.ACCESS_COARSE_LOCATION: This allows the app to access the approximate location of the user.
- Manifest.permission.ACCESS_FINE_LOCATION: This allows the app to access the exact location of the user.
Note that declaring the ACCESS_FINE_LOCATION permission implies the ACCESS_COARSE_LOCATION permission already.
Instantiating the Location Manager
To get a reference of the LocationManager, we use the getSystemService() method, to access the Location Service of the device.
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Setting Up LocationListener
After getting the reference of the LocationManager, now we need to get the current location of the user. To do that we set up the LocationListener – an Event Listener that tells us when the location has changed. This interface has three methods:
- abstract void onLocationChanged(Location location): This method is called when the location has changed. The location object contains all the attributes of the user’s current location, like Latitude, Longitude and Altitude.
- default void onProviderDisabled(String provider): This method is called when the Location Provider (or the location service of the device like GPS) has been disabled by the user.
- default void onProviderEnabled(String provider): This method is called when the Location Provider (or the location service of the device like GPS) has been enabled by the user.
Here is how we set up the LocationListener:
LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(android.location.Location location) { //get the attributes of current location using the location variable //example, location.getLatitude() } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } };
To get the location of the user, we use the requestLocationUpdates() method of LocationManager class. It takes in 4 arguments:
- String provider: a location provider, to see a list of all location providers, use getAllProviders(). This value cannot be null.
- long minTimeMs: minimum time interval between location updates in milliseconds. The location updates will be sent when the time specified by the parameter has passed.
- float minDistanceM: minimum distance between location updates in meters. The location will be updated when the difference between the present location and previous location is greater than or equal to this value.
- LocationListener listener: the listener to receive location updates This value cannot be null.
How to use it in code:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Creating the App
We will now begin creating our app. The function of the app is pretty simple and straightforward: get the location coordinates of the user and display it on the button click. Create a new project with an empty activity.
Defining the Layout
Our layout will have 2 widgets:
- TextView: To display the coordinates
- Button: To get the location coordinates
Open up activity_main.java and write the following:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textview1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="156dp" android:text="Get My Location" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textview1" /> </androidx.constraintlayout.widget.ConstraintLayout>
Adding the Permissions in the Manifest
Open up AndroidManifest.xml, and add these lines above the beginning of the <application> tag:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/>
Permission Handling
We need to ask the user explicitly to grant the permissions required by our app, and if the user denies those permissions, we need to notify them that the action cannot be performed without permission. Every time we perform an action that requires some permissions – e.g. the requestLocationUpdates() method of LocationManager requires location permissions; we need to check whether the permission has already been provided by the user or not. If not, then we will trigger the mechanism that will ask for permissions.
To do that, we use the ActivityCompat.checkSelfPermission() method to check for permissions, and ActivityCompat.requestPermissions to request for the permissions. The function descriptions are as follows:
int checkSelfPermission (Context context, String permission)
The arguments to this method:
- context – The Context of the Activity/Fragment calling this method
- String permission- The name of the permission being checked.
It returns PERMISSION_GRANTED if you have the permission, or PERMISSION_DENIED if not.
void requestPermissions (Activity activity, String[] permissions, int requestCode)
The arguments to this method:
- activity: The target activity.
- String [] permissions: The requested permissions. Must be non-null and not empty.
- requestCode: Application specific request code to match with the result obtained after permission
- request through the onRequestPermissionsResult(). This is useful when we have multiple function
- calls to requestPermissions(), and we need to identify which method call has triggered the callback. Its value should be >= 0.
Here’s how to check for permissions and request permissions for location:
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, PERMISSION); } else { manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MainActivity.this); }
Where PERMISSION is an integer constant. Now, we need to override the onRequestPermissions() method.
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); } else { Toast.makeText(this, "Can't access location without permission", Toast.LENGTH_SHORT).show(); } } }
Wiring up the functionality
Let us now use the different code snippets described in the explanation above to create our app. Open up MainActivity.java, and add the following fields to the file:
LocationManager manager; TextView tv; Button getLocation; private static final int PERMISSION = 200;
- The first field will be used for our main purpose: getting the user’s location.
- The second and third fields are references to our widgets.
- The fourth field is a constant that would be supplied to the requestPermissions() method, as explained above.
We also need to implement the LocationListener. Change the class description as follows:
public class MainActivity extends AppCompatActivity implements LocationListener
We will now need to implement the methods of this interface. Write the following:
@Override public void onLocationChanged(Location location) { tv.setText("Latitude: " + location.getLatitude() + "\nLongitude: " + location.getLongitude() + "\nAltitude: " + location.getAltitude()); } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { }
Add the following code in onCreate():
tv = findViewById(R.id.textview1); getLocation = findViewById(R.id.button); manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); getLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, PERMISSION); } else { manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MainActivity.this); } } });
Finally, override the onRequestPermissionsResult() method, and write the following:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); } else { Toast.makeText(this, "Can't access location without permission", Toast.LENGTH_SHORT).show(); } } }
We have only asked for the ACCESS_FINE_LOCATION permission, as it automatically grants the ACCESS_COARSE_LOCATION permission as well.
Our app is ready, now let us test our app.
App Screenshots
The emulator has a default location whose coordinates are displayed. To change the location, click the 3 horizontal dots at the bottom of the emulator controls menu (located on the right side of the emulator). In the Location menu, choose any location on the map and click ‘Set Location’ (bottom right).