Android SharedPreferences Tutorial and Example

Requesting Location Permissions and Getting GPS Coordinates in Android

Building apps that respond to where the user actually is has become standard practice across Australia. Whether you're plotting a coffee run in Fitzroy, mapping a hike near the Blue Mountains, or tracking a delivery from a Coles storefront in Parramatta, GPS coordinates form the backbone of most location-aware experiences. For Android developers, the challenge is twofold — ask for the right permissions politely and then translate that approval into accurate longitude and latitude values.

The Android permission system has evolved significantly. Gone are the days when installing an app was enough; modern users expect a clear, runtime prompt explaining why your app wants to know their location. A poor permission experience leads to uninstalls, and a denied permission means your location feature simply won't work.

In this guide, we'll walk through requesting location access in an Android application, then fetching the device's current GPS position. You'll see how to declare permissions in the manifest, handle the runtime request, and pull coordinates using the Fused Location Provider.

Before diving into code, it's worth understanding the difference between fine and coarse location in Android. This choice affects everything from battery consumption to coordinate granularity.

Permission Accuracy Typical Use Case Provider
ACCESS_FINE_LOCATION High (a few metres) Turn-by-turn navigation, fitness tracking, geofencing GPS, Wi-Fi, mobile networks
ACCESS_COARSE_LOCATION Lower (hundreds of metres) City-level recommendations, weather, nearest store Wi-Fi and mobile networks only
ACCESS_BACKGROUND_LOCATION High, while in background Continued tracking for delivery or safety apps All providers, with battery implications
No location permission None Apps that don't need location data N/A

Declaring Location Permissions in the Manifest

Android requires every dangerous permission to be declared in AndroidManifest.xml, even before your code requests it at runtime. Without these declarations, the system refuses to show the permission dialog and crashes with a SecurityException when the app tries to read the location.

For GPS-level accuracy, you'll want ACCESS_FINE_LOCATION. If your app can work with a rougher estimate — say, identifying which Australian state capital a user is in, from Adelaide to Darwin — ACCESS_COARSE_LOCATION is sufficient. Some apps request both, which gives the system the flexibility to grant the most appropriate option.

Open AndroidManifest.xml and add the necessary uses-permission entries inside the manifest tag. If you need to fetch the location when your activity isn't visible, you'll also need ACCESS_BACKGROUND_LOCATION, which requires a separate runtime prompt on Android 10 (API level 29) and above.

Checking and Requesting Permissions at Runtime

Manifest declarations alone don't grant the permission. Starting from Android 6.0 (Marshmallow), every dangerous permission must be requested at runtime the first time the user encounters the feature. The flow involves checking whether the permission is already granted, showing a rationale if previously denied, and launching the system dialog using ActivityResultContracts.RequestPermission.

Aussies aren't shy about hitting "Deny" if they don't understand why an app needs their whereabouts. A short, honest explanation — perhaps "We use your location to show nearby trams in Melbourne's CBD" — goes a long way toward earning trust. ContextCompat.checkSelfPermission helps you branch logic depending on whether the user has approved, denied, or permanently rejected the request.

When the user responds to the dialog, the result is delivered back through the launcher you registered. From that callback, you can proceed to fetch the coordinates if the response is positive, or fall back gracefully if not. Calling ActivityCompat.shouldShowRequestPermissionRationale helps you decide whether to display an explanatory screen first.

Getting GPS Coordinates with FusedLocationProviderClient

Once permission is granted, the next step is pulling the actual coordinates. Google Play Services ships a convenient client called FusedLocationProviderClient, which intelligently combines GPS, Wi-Fi, and mobile networks to balance accuracy and battery life. Adding the play-services-location dependency to your build.gradle is the first move.

After instantiating the client, you call requestLocationUpdates or getCurrentLocation. The latter is perfect for one-off fetches — for instance, when a user taps a "Find my nearest bottle-o" button. The result is delivered as a Location object containing getLatitude and getLongitude, plus optional bearing and altitude. You can convert the raw lat/long into a human-readable street address using the Geocoder class, which is handy if you want to display something more meaningful than -33.8688, 151.2093 to your users.

Remember that GPS works best outdoors. If you test inside a building, such as a Brisbane shopping centre, you may notice the first fix takes longer or returns lower accuracy. Heading out to a park — try walking along the Tan in Melbourne or grabbing a coffee at Bondi — usually produces a much faster and more precise result.

Continuous Tracking with LocationRequest

For apps that need ongoing location updates, such as a jogging tracker that follows your run along Sydney's coastline from Coogee to Bondi, a one-off getCurrentLocation call isn't enough. You'll want to set up requestLocationUpdates with a LocationRequest object that defines the interval, priority, and smallest displacement threshold.

A priority of PRIORITY_HIGH_ACCURACY uses GPS and drains the battery quickly, while PRIORITY_BALANCED_POWER_ACCURACY leans on Wi-Fi and networks for a longer-lasting result. For a tradie app tracking travel between job sites around regional Queensland, PRIORITY_LOW_POWER might be perfectly acceptable and far kinder to the battery.

Always unregister the location callback in onStop or when the activity is destroyed. Failing to do so leaves the GPS radio awake and can quickly flatten a phone's charge, particularly during long trips through the bush where coverage keeps hopping between towers.

Handling Denied Permissions Gracefully

Not every user will grant location access, and your app needs to behave sensibly when they don't. When the permission is denied with "Don't ask again" selected, the system will never show your dialog again, and you must send the user to the app's settings page to change their mind. The Settings.ACTION_APPLICATION_DETAILS_SETTINGS intent takes care of this transition smoothly.

It's also wise to provide a clear message inside the app explaining what was lost. A simple "Location is off, so we can't show the nearest cafes in Surry Hills" is more helpful than a silent failure. Many production apps store a flag in SharedPreferences to remember the user's choice and avoid pestering them. For polished UI patterns around the surrounding layout, take a look at using-cardview-with-elevation-and-corner-radius.

If your app absolutely requires location to function — say, a remote-asset tracker operating out near the Pilbara — you may decide to restrict features rather than allow a broken experience. Either way, the principle is the same: be transparent, provide alternatives, and never surprise the user with a sudden permission request.

Displaying Coordinates and Going Further

With coordinates in hand, the possibilities open up. You might display them in a simple TextView for debugging, plot them on a map with the Maps SDK, or use them as inputs for distance calculations. The Location.distanceBetween helper can tell you how far the user is from a fixed point — useful for "are you within 50 metres of the check-in?" features common in Aussie workplace safety apps.

When presenting results to Australian users, remember to format distances in kilometres and use local landmarks when context helps. Telling someone they are 2.3 km from the Sydney Opera House is more relatable than quoting raw metres. You can also use the Geocoder to reverse-geocode coordinates into a suburb name like Fitzroy or Parramatta.

Finally, always test with both permissions granted and denied, on emulators and real devices, and across different Android versions. Australian coverage varies wildly between metro and regional areas, so an app that works in inner Sydney might struggle out near the outback. Stick with it, and the coordinates will start flowing in.