How do I get the current GPS location programmatically in Android?
Asked Answered
D

22

767

I need to get my current location using GPS programmatically. How can i achieve it?

Decolorant answered 3/10, 2009 at 10:59 Comment(0)
M
456

I have created a small application with step by step description to get current location's GPS coordinates.

Complete example source code is in Get Current Location coordinates , City name - in Android.


See how it works:

  • All we need to do is add this permission in the manifest file:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
  • And create a LocationManager instance like this:

    LocationManager locationManager = (LocationManager)
    getSystemService(Context.LOCATION_SERVICE);
    
  • Check if GPS is enabled or not.

  • And then implement LocationListener and get coordinates:

    LocationListener locationListener = new MyLocationListener();
    locationManager.requestLocationUpdates(
    LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
    
  • Here is the sample code to do so


/*---------- Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        editLocation.setText("");
        pb.setVisibility(View.INVISIBLE);
        Toast.makeText(
                getBaseContext(),
                "Location changed: Lat: " + loc.getLatitude() + " Lng: "
                    + loc.getLongitude(), Toast.LENGTH_SHORT).show();
        String longitude = "Longitude: " + loc.getLongitude();
        Log.v(TAG, longitude);
        String latitude = "Latitude: " + loc.getLatitude();
        Log.v(TAG, latitude);

        /*------- To get city name from coordinates -------- */
        String cityName = null;
        Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
            if (addresses.size() > 0) {
                System.out.println(addresses.get(0).getLocality());
                cityName = addresses.get(0).getLocality();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
            + cityName;
        editLocation.setText(s);
    }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

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

Mazur answered 6/6, 2012 at 15:38 Comment(11)
This means you have to be moving before there is a location update? Why doesn't it show your current location on the first time try after install?Jago
@NiiLaryea because I am getting Location using "onLocationChanged()" method which gives every time new location while you move, but if you want just one time, you need to call "getLastKnownLocation()"Mazur
If there is only one address in adresses the line starting with cityName = will fail with an exception. Using braces would fix it.Mccreery
I've heard people say getLastKnownLocation() is a more "stale" location -- why is this? Does calling getLastKnownLocation() not get the latest GPS read of phone's GPS?Expire
@mmcrae No it does not. GPS isn't always running. getLastKnownLocation doesn't turn it on. It gets the last location from the last time it was on. hat could be really fresh, an hour old, or even null.Quesenberry
In many cases it's better to use the overload of requestLocationUpdates which doesn't specify the GPS provider explicitly. LocationManager will then automatically select location providers to optimize battery usage for the requested accuracy.Secretin
I have quesstion on this: https://mcmap.net/q/55425/-getting-location-androidKktp
its taking too much time to get lat-longKristopher
can it bounce off Google Maps to then automatically fill in your address string?Corniculate
I thought the question was "getting the coordinates" (which are two DOUBLES, longitude and latitude). Why all that stuff about city names and toasts and other unnecessary things? Save them for an answer to a different question.Renascence
This wasn't the question. The question merely asks for the value of the two coordinates (longitude and latitude). So, a correct answer to the question should end with two double variables, containing the respective values, ready to be used elsewhere in MainActivity.Renascence
D
47

There are already many answers there but I want to show latest way to get location using Google API, so new programmers can use new method:

I have written detailed tutorial on current location in android at my blog demonuts.com You can also find full source code developed with android studio.

First of all, put this in gradle file

 compile 'com.google.android.gms:play-services:9.0.2'

then implement necessary interfaces

public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

declare instances

  private GoogleApiClient mGoogleApiClient;
  private Location mLocation;
  private LocationManager locationManager;
  private LocationRequest mLocationRequest;

put this in onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

At last, override necessary methods

 @Override
    public void onConnected(Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, 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;
        } startLocationUpdates();
        mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if(mLocation == null){
            startLocationUpdates();
        }
        if (mLocation != null) {
            double latitude = mLocation.getLatitude();
            double longitude = mLocation.getLongitude();
        } else {
            // Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
        }
    }

    protected void startLocationUpdates() {
        // Create the location request
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)
                .setFastestInterval(FASTEST_INTERVAL);
        // Request location updates
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, 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;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest, this);
        Log.d("reque", "--->>>>");
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection Suspended");
        mGoogleApiClient.connect();
    }

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

    @Override
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }
    @Override
    public void onLocationChanged(Location location) {

    }

Don't forget to start GPS in your device before running app.

Denby answered 20/3, 2016 at 6:31 Comment(5)
I used your method to display coordinates but i am unable to see the coordinates can you please look into my question ?Ilia
mLocation always gives null. I tried the same as mentionedLatinist
Go to this link : demonuts.com/2016/12/30/get-current-gps-location-android-studio and download source code from there and check if source code is working in your pc or notDenby
This should be the accepted answer. And for compactness, you can use compile 'com.google.android.gms:play-services-location:11.0.4' instead of adding all google play services to your app.Sardinia
This should not be the accepted answer, because google play services and GMS is not available on AOSP. The question was for access to the GPS system directly. I have a similar problem, and cannot use GMS on the custom hardware.Carditis
Q
42

Since I didn't like some of the code in the other answers, here's my simple solution. This solution is meant to be usable in an Activity or Service to track the location. It makes sure that it never returns data that's too stale unless you explicitly request stale data. It can be run in either a callback mode to get updates as we receive them, or in poll mode to poll for the most recent info.

Generic LocationTracker interface. Allows us to have multiple types of location trackers and plug the appropriate one in easily:

package com.gabesechan.android.reusable.location;

import android.location.Location;

public interface LocationTracker {
    public interface LocationUpdateListener{
        public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime);
    }

    public void start();
    public void start(LocationUpdateListener update);

    public void stop();

    public boolean hasLocation();

    public boolean hasPossiblyStaleLocation();

    public Location getLocation();

    public Location getPossiblyStaleLocation();

}

ProviderLocationTracker- this class will track the location for either GPS or NETWORK.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener, LocationTracker {

    // The minimum distance to change Updates in meters
    private static final long MIN_UPDATE_DISTANCE = 10; 

    // The minimum time between updates in milliseconds
    private static final long MIN_UPDATE_TIME = 1000 * 60; 

    private LocationManager lm;

    public enum ProviderType{
        NETWORK,
        GPS
    };    
    private String provider;

    private Location lastLocation;
    private long lastTime;

    private boolean isRunning;

    private LocationUpdateListener listener;

    public ProviderLocationTracker(Context context, ProviderType type) {
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        if(type == ProviderType.NETWORK){
            provider = LocationManager.NETWORK_PROVIDER;
        }
        else{
            provider = LocationManager.GPS_PROVIDER;
        }
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //The provider is on, so start getting updates.  Update current location
        isRunning = true;
        lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
        lastLocation = null;
        lastTime = 0;
        return;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;

    }


    public void stop(){
        if(isRunning){
            lm.removeUpdates(this);
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        if(lastLocation == null){
            return false;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return false; //stale
        }
        return true;
    }

    public boolean hasPossiblyStaleLocation(){
        if(lastLocation != null){
            return true;
        }
        return lm.getLastKnownLocation(provider)!= null;
    }

    public Location getLocation(){
        if(lastLocation == null){
            return null;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return null; //stale
        }
        return lastLocation;
    }

    public Location getPossiblyStaleLocation(){
        if(lastLocation != null){
            return lastLocation;
        }
        return lm.getLastKnownLocation(provider);
    }

    public void onLocationChanged(Location newLoc) {
        long now = System.currentTimeMillis();
        if(listener != null){
            listener.onUpdate(lastLocation, lastTime, newLoc, now);
        }
        lastLocation = newLoc;
        lastTime = now;
    }

    public void onProviderDisabled(String arg0) {

    }

    public void onProviderEnabled(String arg0) {

    }

    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }
}

The is the FallbackLocationTracker, which will track by both GPS and NETWORK, and use whatever location is more accurate.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {


    private boolean isRunning;

    private ProviderLocationTracker gps;
    private ProviderLocationTracker net;

    private LocationUpdateListener listener;

    Location lastLoc;
    long lastTime;

    public FallbackLocationTracker(Context context) {
        gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
        net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //Start both
        gps.start(this);
        net.start(this);
        isRunning = true;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;
    }


    public void stop(){
        if(isRunning){
            gps.stop();
            net.stop();
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        //If either has a location, use it
        return gps.hasLocation() || net.hasLocation();
    }

    public boolean hasPossiblyStaleLocation(){
        //If either has a location, use it
        return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
    }

    public Location getLocation(){
        Location ret = gps.getLocation();
        if(ret == null){
            ret = net.getLocation();
        }
        return ret;
    }

    public Location getPossiblyStaleLocation(){
        Location ret = gps.getPossiblyStaleLocation();
        if(ret == null){
            ret = net.getPossiblyStaleLocation();
        }
        return ret;
    }

    public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
        boolean update = false;

        //We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
        if(lastLoc == null){
            update = true;
        }
        else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
            update = true;
        }
        else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
            update = true;
        }
        else if (newTime - lastTime > 5 * 60 * 1000){
            update = true;
        }

        if(update){
            if(listener != null){
                listener.onUpdate(lastLoc, lastTime, newLoc, newTime);                  
            }
            lastLoc = newLoc;
            lastTime = newTime;
        }

    }
}

Since both implement the LocationTracker interface, you can easily change your mind about which one to use. To run the class in poll mode, just call start(). To run it in update mode, call start(Listener).

Also take a look at my blog post on the code

Quesenberry answered 8/7, 2014 at 4:18 Comment(16)
For anyone curious- the reason I don't use the times built into the Location object is because the API doesn't exist until API 17. Since I want to keep compatibility to 14, I just use the current time. That's also why I don't call getLastKnownLocation early- because we can't get a time from it and see if its stale.Quesenberry
Your code is the best and the most complete solution I have found in last two days of search on this subject. It works without any errors and like a charm, its impressive. Just one thing, I changed FallbackLocationTracker(Context context, ProviderType type), to public FallbackLocationTracker(Context context) since we don't need to send a provider to this class, it takes into account both GPS and the Network, am I right?Herzen
@Herzen You're correct, and I updated the code here. I'll do it on my blog next time I find some time (a hard to get resource for me these days). As you probably guessed, I created the fallback by copy pasting from the other class and never made that cleanup.Quesenberry
I have found out that its the Google Play API which gives more accurate location and not the default API. In default APIs we get very stale locations, whereas at the same time Google Maps shows you much more accurate location even when you are offline for a while. This is because they use their Play API.Herzen
Sorry, that isn't quite right @zeeshan. Google Play uses a combination of GPS and network. GPS_PROVIDER is more accurate and updates far more frequently, once its synched but uses more battery. The fusion provider in the Play API may do better than NETWORK_PROVIDER, but that's because its using some GPS information to improve the results at the cost of battery. The problem is that the user has to have Play installed, which they may not (custom ROMs and any OEM that hasn't paid google won't, unless they pirate it).Quesenberry
Thanks for this insight. However on my device and a few friends who tested my app, NETWORK_PROVIDER coordinates are days or weeks old and they don't get updated unless devices are restarted, whereas Google Maps coordinates are much more accurate despite GPS being off. My ambient app doesn't work due to such stale coordinates. Is using Play API my only option?Herzen
Days or weeks old? That sounds like something wrong with their phone- I've seen minutes old, longer than that and Android generally won't return them. I've never seen days old.Quesenberry
Nice answer, very well structured. Just a remark, in the FallbackLocationTracker class, in the method onUpdate, in the end, the variables lastLoc and lastTime should be updated after calling the method onUpdate from the listener. Otherwise, both last and current parameters will be the same.Cobwebby
best solution..but lacking only one thing...A beginner can't implement it..there should be a usage example in it too..Brunhilda
hello @GabeSechan I've implemented your method, but everytime that I turn on the GPS in settings on my android device and leave the Network on, it always return null on getLocation method. FallbackLocationTracker fallbackLocationTracker = new FallbackLocationTracker(mContext); fallbackLocationTracker.start(); if (fallbackLocationTracker.hasLocation()) { return fallbackLocationTracker.getLocation(); }Overtrade
please add usage example.Becka
Hey, I want to get location, but am having this problem: https://mcmap.net/q/55425/-getting-location-androidKktp
how to use this ? it is returning me nullFalcone
FallbackLocationTracker tracker = new FallbackLocationTracker(MainActivity.this); tracker.start(new LocationTracker.LocationUpdateListener() { @Override public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) { } }); Location location = tracker.getPossiblyStaleLocation();Falcone
getPossiblyStaleLocation will return null at times. It means the system doesn't have a location to return, even a stale one.Quesenberry
You can add this to your project by calling this where you need it registered in your app FallbackLocationTracker tracker = new FallbackLocationTracker(MainActivity.this); tracker.start(new LocationTracker.LocationUpdateListener() { @Override public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) { if(newLoc == null) { if(oldLoc != null) youLocationVariable = oldLoc; } else yourLocationVariable = newLoc; } });Phony
R
27

As of the second half of 2020, there is a much easier way to do this.

Excluding requesting permissions (which I will include at the bottom for devs newer to this), below is the code.

Just remember, you need to include at least this version of the library in your dependencies (in the app's build.gradle):

implementation 'com.google.android.gms:play-services-location:17.1.0'

... and of course the fine permission in your manifest:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Kotlin (first the setup):

private val fusedLocationClient: FusedLocationProviderClient by lazy {
    LocationServices.getFusedLocationProviderClient(applicationContext)
}

private var cancellationTokenSource = CancellationTokenSource()

Then the main code (for FINE_LOCATION):

private fun requestCurrentLocation() {
    // Check Fine permission
    if (ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION) ==
        PackageManager.PERMISSION_GRANTED) {

        // Main code
        val currentLocationTask: Task<Location> = fusedLocationClient.getCurrentLocation(
            PRIORITY_HIGH_ACCURACY,
            cancellationTokenSource.token
        )

        currentLocationTask.addOnCompleteListener { task: Task<Location> ->
            val result = if (task.isSuccessful) {
                val result: Location = task.result
                "Location (success): ${result.latitude}, ${result.longitude}"
            } else {
                val exception = task.exception
                "Location (failure): $exception"
            }

            Log.d(TAG, "getCurrentLocation() result: $result")
        }
    } else {
        // Request fine location permission (full code below).
}

If you prefer Java, it looks like this:

public class JavaVersion extends AppCompatActivity {

    private final String TAG = "MainActivity";

    // The Fused Location Provider provides access to location APIs.
    private FusedLocationProviderClient fusedLocationClient;

    // Allows class to cancel the location request if it exits the activity.
    // Typically, you use one cancellation source per lifecycle.
    private final CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    }
    ...
    
    private void requestCurrentLocation() {
        Log.d(TAG, "requestCurrentLocation()");
        // Request permission
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION) ==
                PackageManager.PERMISSION_GRANTED) {
            
            // Main code
            Task<Location> currentLocationTask = fusedLocationClient.getCurrentLocation(
                    PRIORITY_HIGH_ACCURACY,
                    cancellationTokenSource.getToken()
            );

            currentLocationTask.addOnCompleteListener((new OnCompleteListener<Location>() {
                @Override
                public void onComplete(@NonNull Task<Location> task) {

                    String result = "";

                    if (task.isSuccessful()) {
                        // Task completed successfully
                        Location location = task.getResult();
                        result = "Location (success): " +
                                location.getLatitude() +
                                ", " +
                                location.getLongitude();
                    } else {
                        // Task failed with an exception
                        Exception exception = task.getException();
                        result = "Exception thrown: " + exception;
                    }

                    Log.d(TAG, "getCurrentLocation() result: " + result);
                }
            }));
        } else {
            // TODO: Request fine location permission
            Log.d(TAG, "Request fine location permission.");
        }
    }
    ...
}

The arguments:

  1. PRIORITY type is self-explanatory. (Other options are PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, and PRIORITY_NO_POWER.)
  2. CancellationToken - This allows you to cancel the request if, for instance, the user navigates away from your Activity.

Example (Kotlin):

override fun onStop() {
    super.onStop()
    // Cancels location request (if in flight).
    cancellationTokenSource.cancel()
}

That's it.

Now, this does use the FusedLocationProviderClient which is a Google Play Services APIs.

That means this works on all Android devices with the Google Play Store (which is a lot of them). However, for devices in China without the Play Store, this won't work, so take that into account.

For developers who are a little newer to this, you need to request the fine (or coarse) location permission if the user hasn't approved it yet, so in the code above, I would request the location permission.

Below is the full code (in Kotlin).

I hope that helps (and makes your live's a little easier)!

/**
 * Demonstrates how to easily get the current location via the [FusedLocationProviderClient.getCurrentLocation].
 * The main code is in this class's requestCurrentLocation() method.
 */
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    // The Fused Location Provider provides access to location APIs.
    private val fusedLocationClient: FusedLocationProviderClient by lazy {
        LocationServices.getFusedLocationProviderClient(applicationContext)
    }

    // Allows class to cancel the location request if it exits the activity.
    // Typically, you use one cancellation source per lifecycle.
    private var cancellationTokenSource = CancellationTokenSource()

    // If the user denied a previous permission request, but didn't check "Don't ask again", this
    // Snackbar provides an explanation for why user should approve, i.e., the additional rationale.
    private val fineLocationRationalSnackbar by lazy {
        Snackbar.make(
            binding.container,
            R.string.fine_location_permission_rationale,
            Snackbar.LENGTH_LONG
        ).setAction(R.string.ok) {
            requestPermissions(
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE
            )
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root

        setContentView(view)
    }

    override fun onStop() {
        super.onStop()
        // Cancels location request (if in flight).
        cancellationTokenSource.cancel()
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        Log.d(TAG, "onRequestPermissionResult()")

        if (requestCode == REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE) {
            when {
                grantResults.isEmpty() ->
                    // If user interaction was interrupted, the permission request
                    // is cancelled and you receive an empty array.
                    Log.d(TAG, "User interaction was cancelled.")

                grantResults[0] == PackageManager.PERMISSION_GRANTED ->
                    Snackbar.make(
                        binding.container,
                        R.string.permission_approved_explanation,
                        Snackbar.LENGTH_LONG
                    )
                        .show()

                else -> {
                    Snackbar.make(
                        binding.container,
                        R.string.fine_permission_denied_explanation,
                        Snackbar.LENGTH_LONG
                    )
                        .setAction(R.string.settings) {
                            // Build intent that displays the App settings screen.
                            val intent = Intent()
                            intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                            val uri = Uri.fromParts(
                                "package",
                                BuildConfig.APPLICATION_ID,
                                null
                            )
                            intent.data = uri
                            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                            startActivity(intent)
                        }
                        .show()
                }
            }
        }
    }

    fun locationRequestOnClick(view: View) {
        Log.d(TAG, "locationRequestOnClick()")

        requestCurrentLocation()
    }

    /**
     * Gets current location.
     * Note: The code checks for permission before calling this method, that is, it's never called
     * from a method with a missing permission. Also, I include a second check with my extension
     * function in case devs just copy/paste this code.
     */
    private fun requestCurrentLocation() {
        Log.d(TAG, "requestCurrentLocation()")
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED) {

            // Returns a single current location fix on the device. Unlike getLastLocation() that
            // returns a cached location, this method could cause active location computation on the
            // device. A single fresh location will be returned if the device location can be
            // determined within reasonable time (tens of seconds), otherwise null will be returned.
            //
            // Both arguments are required.
            // PRIORITY type is self-explanatory. (Other options are PRIORITY_BALANCED_POWER_ACCURACY,
            // PRIORITY_LOW_POWER, and PRIORITY_NO_POWER.)
            // The second parameter, [CancellationToken] allows the activity to cancel the request
            // before completion.
            val currentLocationTask: Task<Location> = fusedLocationClient.getCurrentLocation(
                PRIORITY_HIGH_ACCURACY,
                cancellationTokenSource.token
            )

            currentLocationTask.addOnCompleteListener { task: Task<Location> ->
                val result = if (task.isSuccessful) {
                    val result: Location = task.result
                    "Location (success): ${result.latitude}, ${result.longitude}"
                } else {
                    val exception = task.exception
                    "Location (failure): $exception"
                }

                Log.d(TAG, "getCurrentLocation() result: $result")
                logOutputToScreen(result)
            }
        } else {
            val provideRationale = shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)

            if (provideRationale) {
                fineLocationRationalSnackbar.show()
            } else {
                requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE)
            }
        }
    }

    private fun logOutputToScreen(outputString: String) {
        val finalOutput = binding.outputTextView.text.toString() + "\n" + outputString
        binding.outputTextView.text = finalOutput
    }

    companion object {
        private const val TAG = "MainActivity"
        private const val REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE = 34
    }
}
Regretful answered 4/12, 2020 at 19:24 Comment(11)
I also created a full sample you can see in the android github repo for location. I hope that helps!Regretful
Thanks for your uptodate codes. Only problem that I can't find solution for it is the case of a new device or a device that has been restored to factory settings. Task is not successful & it returns null. The device tested is Xiaomi Redmi Note 10, Android11 .Have you any suggestion for it?Holifield
I'm not familiar with that device, does it have Google Play Store? If yes, there are some cases when you could get a null (from my understanding): 1. When the device is not able to compute the location 2. When the app is calling this API from the background (I think you need location background permissions there would be my guess)Regretful
@Regretful can you add code for checking if location is turned on? Specificaly using ResolvableApiException!???Concourse
but if we dont use the library it would be preferrable as the size is growing rapidly.... :DOatmeal
Finally get current location exempleGarret
@codingjeremy: regards to your 'full sample': Github Error: The 'android/location-samples' repository doesn't contain the 'CurrentLocationKotlin' path in 'main'.Hoy
Oh shoot, looks like it was removed. I've since changed teams but here it is from the git history.Regretful
There looks like there is another sample with some similar info if you want to see another example.Regretful
If location requests would be very fast under all circumstances your example would work well in real world, I think. I need a good location as fast as possible if my users press a button to send data. The solution is fusedLocationClient.requestLocationUpdates().Bea
@codingjeremy: Why in it has been set minSdkVersion = 27?Hoy
L
21

Get location of gps by -

LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

LocationListener locationListener = new LocationListener() 
{

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {
                // TODO Auto-generated method stub
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                double speed = location.getSpeed(); //spedd in meter/minute
                speed = (speed*3600)/1000;      // speed in km/minute               Toast.makeText(GraphViews.this, "Current speed:" + location.getSpeed(),Toast.LENGTH_SHORT).show();
            }
        };

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

}
Langan answered 4/2, 2015 at 9:5 Comment(3)
The goal is always less more precise code and not overdoing simple location check like so many of the other answers. Thank you for actually answering the question that was asked.Blankbook
How to get location every 1 secondKktp
Thanks for the simple way to get GPS, it works! A microbug: location.getSpeed() returns speed in meter/sec (not meter/min).Sada
D
18

You need to use latest/newest

GoogleApiClient Api

Basically what you need to do is:

private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Then

@Override
    public void onConnected(Bundle connectionHint) {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
            mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
        }
    }

for the most accurate and reliable location. See my post here:

https://mcmap.net/q/55427/-longitude-and-latiude-null-in-android

Do not use LocationListener which is not accurate and has delayed response. To be honest this is easier to implement. Also read documentation: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient

Dielle answered 8/11, 2015 at 21:41 Comment(2)
This is the best answer for the latest API.Blip
Yes. This is the right way to do it, these days. @nickfox provided some good links in his second answer to this question, from the original creators of the Location Services API, that are worth checking out.Icaria
M
11
class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;

    public boolean getLocation(Context context, LocationResult result) {
        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        if (lm == null)
            lm = (LocationManager) context
                    .getSystemService(Context.LOCATION_SERVICE);

        // Exceptions will be thrown if the provider is not permitted.
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }
        catch (Exception ex) {
        }
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }
        catch (Exception ex) {
        }

        // Don't start listeners if no provider is enabled.
        if (!gps_enabled && !network_enabled)
            return false;

        if (gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                    locationListenerGps);
        if (network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                    locationListenerNetwork);
        timer1 = new Timer();
        timer1.schedule(new GetLastLocation(), 5000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            Location net_loc = null, gps_loc = null;
            if (gps_enabled)
                gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (network_enabled)
                net_loc = lm
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            // If there are both values, use the latest one.
            if (gps_loc != null && net_loc != null) {
                if (gps_loc.getTime() > net_loc.getTime())
                    locationResult.gotLocation(gps_loc);
                else
                    locationResult.gotLocation(net_loc);
                return;
            }

            if (gps_loc != null) {
                locationResult.gotLocation(gps_loc);
                return;
            }
            if (net_loc != null) {
                locationResult.gotLocation(net_loc);
                return;
            }
            locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }
}

I hope this will help you...

Multiform answered 16/12, 2013 at 11:49 Comment(1)
Don't forget to add following line to your AndroidManifest file: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />Cucumber
B
9

Now that Google Play locations services are here, I recommend that developers start using the new fused location provider. You will find it easier to use and more accurate. Please watch the Google I/O video Beyond the Blue Dot: New Features in Android Location by the two guys who created the new Google Play location services API.

I've been working with location APIs on a number of mobile platforms, and I think what these two guys have done is really revolutionary. It's gotten rid of a huge amount of the complexities of using the various providers. Stack Overflow is littered with questions about which provider to use, whether to use last known location, how to set other properties on the LocationManager, etc. This new API that they have built removes most of those uncertainties and makes the location services a pleasure to use.

I've written an Android app that periodically gets the location using Google Play location services and sends the location to a web server where it is stored in a database and can be viewed on Google Maps. I've written both the client software (for Android, iOS, Windows Phone and Java ME) and the server software (for ASP.NET and SQL Server or PHP and MySQL). The software is written in the native language on each platform and works properly in the background on each. Lastly, the software has the MIT License. You can find the Android client here:

https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android

Blimp answered 4/2, 2014 at 6:56 Comment(0)
T
7

GoogleSamples has verbose example using latest FusedLocationProviderApi. Unfortunately the most upvoted answers are out of date.

Follow the below examples to implement Location Services using FusedLocationProviderApi

https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java

Tahmosh answered 9/11, 2017 at 20:56 Comment(0)
G
6

LocationManager is a class that provides in-build methods to get last know location

STEP 1 :Create a LocationManager Object as below

LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

STEP 2 : Add Criteria

*Criteria is use for setting accuracy*

Criteria criteria = new Criteria();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;

if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {

    criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(true);
    criteria.setBearingRequired(true);
    criteria.setSpeedRequired(true);

}

STEP 3 :GET Avaliable Provider

Threre are two types of provider GPS and network

 String provider = locationManager.getBestProvider(criteria, true);

STEP 4: Get Last Know Location

Location location = locationManager.getLastKnownLocation(provider);

STEP 5: Get Latitude and Longitude

If location object is null then dont try to call below methods

getLatitude and getLongitude is methods which returns double values

Golfer answered 4/1, 2016 at 9:14 Comment(0)
G
6

Getting location updates requires lots of bolierplate code in Android, You need to take care of

  • Google Play services availablity Check,
  • Update Google play Service if it is old or not available
  • Dialog Creation of GoogleApiClient and its callbacks connected,disconnected etc.
  • Stopping and releasing resources for location updates
  • Handling Location permission scenarios
  • Checking Location services are On or Off
  • Getting lastknown location is not so easy either
  • Fallback to last known location if not getting location after certain duration

To ease out all these steps i have created Android-EasyLocation (small android library) which will take care all this stuff and you can focus on business logic.

All you need is extend EasyLocationActivity and this

requestSingleLocationFix(easyLocationRequest);

or

requestLocationUpdates(easyLocationRequest);

Checkout sample app and steps needed here at https://github.com/akhgupta/Android-EasyLocation

Gadabout answered 7/11, 2016 at 10:8 Comment(0)
A
6

Since September 23, 2020 play-services-location version 17.1.0 includes FusedLocationProviderClient.getCurrentLocation() method which is the recommended and straightforward way to get the current location:

Returns a single current location fix on the device. Unlike getLastLocation() that returns a cached location, this method could cause active location computation on the device. A single fresh location will be returned if the device location can be determined within reasonable time (tens of seconds), otherwise null will be returned.

For a detailed example take a look at codingjeremy's answer and an official Android location sample on GitHub - Current Location (Kotlin).

Administrate answered 25/12, 2020 at 10:24 Comment(2)
Current Location (Kotlin) 404 - page not found.Hoy
I edited the answer to link to the archive.org version of Current Location (Kotlin).Gerena
F
5

I have made a project from which we can get the accurate location using Google Play Services, GPS and Network providers. This project can be found here.

Strategy in finding the best location is that first get the location from google play services if location is found then check weather it is better or not, if location found is null restart google play services and try to fetch the location from Android Location API. Register the location on change listeners and when ever the better location is found the call back returns it to the main activity.

It is very simple to use and implement in code only two classes we need to embed i.e. LocationManagerInterface and SmartLocationManager, LocationActivity is implementing the interface and using SmartLocationManager to fetch location.

/**
 * Created by Syed Raza Mehdi Naqvi on 8/10/2016.
 */
public interface LocationManagerInterface {
    String TAG = LocationManagerInterface.class.getSimpleName();

    void locationFetched(Location mLocation, Location oldLocation, String time, String locationProvider);

}

here is the location manager class

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

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.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

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

/**
 * Created by Syed Raza Mehdi Naqvi on 8/9/2016.
 */
public class SmartLocationManager implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final String TAG = SmartLocationManager.class.getSimpleName();

    private static final int TWO_MINUTES = 1000 * 60 * 2;
    private static final int PERMISSION_REQUEST_CODE = 1000;
    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    // default value is false but user can change it
    private String mLastLocationUpdateTime;                                                         // fetched location time
    private String locationProvider;                                                                // source of fetched location

    private Location mLastLocationFetched;                                                          // location fetched
    private Location mLocationFetched;                                                              // location fetched
    private Location networkLocation;
    private Location gpsLocation;

    private int mLocationPiority;
    private long mLocationFetchInterval;
    private long mFastestLocationFetchInterval;

    private Context mContext;                                                                       // application context
    private Activity mActivity;                                                                     // activity context
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationManagerInterface mLocationManagerInterface;

    private android.location.LocationManager locationManager;
    private android.location.LocationListener locationListener;

    boolean isGPSEnabled;
    boolean isNetworkEnabled;

    private int mProviderType;
    public static final int NETWORK_PROVIDER = 1;
    public static final int ALL_PROVIDERS = 0;
    public static final int GPS_PROVIDER = 2;

//    private final double STANDARD_LOCATION_ACCURACY = 100.0;
//    private final double STANDARD_LOCATION_SEED_LIMIT = 6.95;

    public static final int LOCATION_PROVIDER_ALL_RESTICTION = 1;
    public static final int LOCATION_PROVIDER_RESTRICTION_NONE = 0;
    public static final int LOCATION_PROVIDER_GPS_ONLY_RESTICTION = 2;
    public static final int LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION = 3;
    private int mForceNetworkProviders = 0;

    public SmartLocationManager(Context context, Activity activity, LocationManagerInterface locationInterface, int providerType, int locationPiority, long locationFetchInterval, long fastestLocationFetchInterval, int forceNetworkProviders) {
        mContext = context;
        mActivity = activity;
        mProviderType = providerType;

        mLocationPiority = locationPiority;
        mForceNetworkProviders = forceNetworkProviders;
        mLocationFetchInterval = locationFetchInterval;
        mFastestLocationFetchInterval = fastestLocationFetchInterval;

        mLocationManagerInterface = locationInterface;

        initSmartLocationManager();
    }


    public void initSmartLocationManager() {

        // 1) ask for permission for Android 6 above to avoid crash
        // 2) check if gps is available
        // 3) get location using awesome strategy

        askLocationPermission();                            // for android version 6 above
        checkNetworkProviderEnable(mForceNetworkProviders);                       //

        if (isGooglePlayServicesAvailable())                // if googleplay services available
            initLocationObjts();                            // init obj for google play service and start fetching location
        else
            getLocationUsingAndroidAPI();                   // otherwise get location using Android API
    }

    private void initLocationObjts() {
        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(mLocationPiority)
                .setInterval(mLocationFetchInterval)                    // 10 seconds, in milliseconds
                .setFastestInterval(mFastestLocationFetchInterval);     // 1 second, in milliseconds

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        startLocationFetching();                                        // connect google play services to fetch location
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        startLocationUpdates();
        if (location == null) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            getLocationUsingAndroidAPI();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            getLastKnownLocation();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST); // Start an Activity that tries to resolve the error
                getLocationUsingAndroidAPI();                                                                // try to get location using Android API locationManager
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    private void setNewLocation(Location location, Location oldLocation) {
        if (location != null) {
            mLastLocationFetched = oldLocation;
            mLocationFetched = location;
            mLastLocationUpdateTime = DateFormat.getTimeInstance().format(new Date());
            locationProvider = location.getProvider();
            mLocationManagerInterface.locationFetched(location, mLastLocationFetched, mLastLocationUpdateTime, location.getProvider());
        }
    }

    private void getLocationUsingAndroidAPI() {
        // Acquire a reference to the system Location Manager
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        setLocationListner();
        captureLocation();
    }

    public void captureLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        try {
            if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
            } else {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private void setLocationListner() {
        // Define a listener that responds to location updates
        locationListener = new android.location.LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                if (location == null) {
                    getLastKnownLocation();
                } else {
                    setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    if (isLocationAccurate(location) && location.getAccuracy() < STANDARD_LOCATION_ACCURACY && location.getSpeed() < STANDARD_LOCATION_SEED_LIMIT) {// no use of this if
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    } else {
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    }
                }
            }

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

            public void onProviderEnabled(String provider) {
            }

            public void onProviderDisabled(String provider) {
            }
        };
    }

    public Location getAccurateLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            Location newLocalGPS, newLocalNetwork;
            if (gpsLocation != null || networkLocation != null) {
                newLocalGPS = getBetterLocation(mLocationFetched, gpsLocation);
                newLocalNetwork = getBetterLocation(mLocationFetched, networkLocation);
                setNewLocation(getBetterLocation(newLocalGPS, newLocalNetwork), mLocationFetched);
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage());
        }
        return mLocationFetched;
    }

    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    public void startLocationFetching() {
        mGoogleApiClient.connect();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    public void pauseLocationFetching() {
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }

    }

    public void abortLocationFetching() {
        mGoogleApiClient.disconnect();

        // Remove the listener you previously added
        if (locationManager != null && locationListener != null) {
            if (Build.VERSION.SDK_INT >= 23 &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            try {
                locationManager.removeUpdates(locationListener);
                locationManager = null;
            } catch (Exception ex) {
                Log.e(TAG, ex.getMessage());

            }
        }
    }

    public void resetLocation() {
        mLocationFetched = null;
        mLastLocationFetched = null;
        networkLocation = null;
        gpsLocation = null;
    }

    //  Android M Permission check
    public void askLocationPermission() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


            if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    ) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
                        || ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) {

                    final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
                    builder.setMessage("Please allow all permissions in App Settings for additional functionality.")
                            .setCancelable(false)
                            .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    Toast.makeText(mContext, "Welcome", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    mActivity.finish();
                                }
                            });
                    final AlertDialog alert = builder.create();
                    alert.show();

                } else
                    ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
                            , Manifest.permission.ACCESS_FINE_LOCATION
                    }, PERMISSION_REQUEST_CODE);

            }
        }
    }

    public void checkNetworkProviderEnable(int enforceActive) {
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            buildAlertMessageTurnOnLocationProviders("Your location providers seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isGPSEnabled && mForceNetworkProviders == LOCATION_PROVIDER_GPS_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your GPS seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isNetworkEnabled && mForceNetworkProviders == LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your Network location provider seems to be disabled, please enable it", "OK", "Cancel");
        }
        // getting network status

        if (!isGPSEnabled && !isNetworkEnabled) {
            Toast.makeText(mContext, "Location can't be fetched!", Toast.LENGTH_SHORT).show(); // show alert
            mActivity.finish();
        }
    }

    private void buildAlertMessageTurnOnLocationProviders(String message, String positiveButtonText, String negativeButtonText) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
        builder.setMessage(message)
                .setCancelable(false)
                .setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        Intent mIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(mIntent);
                    }
                })
                .setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        mActivity.finish();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }


    public Location getLastKnownLocation() {
        locationProvider = LocationManager.NETWORK_PROVIDER;
        Location lastKnownLocation = null;
        // Or use LocationManager.GPS_PROVIDER
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return lastKnownLocation;
        }
        try {
            lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
            return lastKnownLocation;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return lastKnownLocation;
    }

    public boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);

        if (status == ConnectionResult.SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Determines whether one Location reading is better than the current Location fix
     *
     * @param location            The new Location that you want to evaluate
     * @param currentBestLocation The current Location fix, to which you want to compare the new one
     */
    protected Location getBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return location;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return location;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return currentBestLocation;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return location;
        } else if (isNewer && !isLessAccurate) {
            return location;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return location;
        }
        return currentBestLocation;
    }

    /**
     * Checks whether two providers are the same
     */

    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    public boolean isLocationAccurate(Location location) {
        if (location.hasAccuracy()) {
            return true;
        } else {
            return false;
        }
    }

    public Location getStaleLocation() {
        if (mLastLocationFetched != null) {
            return mLastLocationFetched;
        }
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        } else {
            return getBetterLocation(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
        }
    }
}

we can use it with activity or a fragment, here i am using it with activity

import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.example.raza.locationaware.location.LocationManagerInterface;
import com.example.raza.locationaware.location.SmartLocationManager;
import com.google.android.gms.location.LocationRequest;

public class LocationActivity extends AppCompatActivity implements LocationManagerInterface {

    public static final String TAG = LocationActivity.class.getSimpleName();

    SmartLocationManager mLocationManager;
    TextView mLocalTV, mLocationProviderTV, mlocationTimeTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        mLocationManager = new SmartLocationManager(getApplicationContext(), this, this, SmartLocationManager.ALL_PROVIDERS, LocationRequest.PRIORITY_HIGH_ACCURACY, 10 * 1000, 1 * 1000, SmartLocationManager.LOCATION_PROVIDER_RESTRICTION_NONE); // init location manager
        mLocalTV = (TextView) findViewById(R.id.locationDisplayTV);
        mLocationProviderTV = (TextView) findViewById(R.id.locationProviderTV);
        mlocationTimeTV = (TextView) findViewById(R.id.locationTimeFetchedTV);
    }

    protected void onStart() {
        super.onStart();
        mLocationManager.startLocationFetching();
    }

    protected void onStop() {
        super.onStop();
        mLocationManager.abortLocationFetching();
    }

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

    @Override
    public void locationFetched(Location mLocal, Location oldLocation, String time, String locationProvider) {
        Toast.makeText(getApplication(), "Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude(), Toast.LENGTH_LONG).show();
        mLocalTV.setText("Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude());
        mLocationProviderTV.setText(locationProvider);
        mlocationTimeTV.setText(time);
    }
}

Hope it helps, if you can suggest any improvement kindly post it on git. Thanks.

Furtado answered 11/8, 2016 at 13:13 Comment(0)
B
5

I have got very accurate location using FusedLocationProviderClient
(Google Play services required)

Permissions Required

android.permission.ACCESS_FINE_LOCATION

android.permission.ACCESS_COARSE_LOCATION

Dependency

'com.google.android.gms:play-services-location:15.0.0'

Kotlin Code

val client = FusedLocationProviderClient(this)
val location = client.lastLocation
location.addOnCompleteListener {
    // this is a lambda expression and we get an 'it' iterator to access the 'result'
    // it.result.latitude gives the latitude
    // it.result.longitude gives the longitude 
    val geocoder = Geocoder(applicationContext, Locale.getDefault())
    val address = geocoder.getFromLocation(it.result.latitude, it.result.longitude, 1)
    if (address != null && address.size > 0) {
        // Get the current city
        city = address[0].locality
    }
}
location.addOnFailureListener {
    // Some error in getting the location, let's log it
    Log.d("xtraces", it.message)
}
Baptiste answered 8/5, 2018 at 9:4 Comment(0)
A
4

For just location checking you can use following code. You can put it in your onStart() of main activity and display alert dialog if return is false.

private boolean isLocationAccurate()
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
        {
            String provider = Settings.Secure
                    .getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            if (provider != null && !provider.contains("gps"))
            {
                return false;
            }
        }
        else
        {
            try
            {
                int status = Settings.Secure
                        .getInt(this.getContentResolver(), Settings.Secure.LOCATION_MODE);
                if (status != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY)
                {
                    return false;
                }
            }
            catch (Settings.SettingNotFoundException e)
            {
                Log.e(TAG, e.getMessage());
            }
        }

        return true;
    }
Aminta answered 21/10, 2014 at 16:15 Comment(0)
B
3

If you are creating new location projects for Android you should use the new Google Play location services. It is much more accurate and much simpler to use.

I have been working on an open source GPS tracker project, GpsTracker, for several years. I recently updated it to handle periodic updates from Android, iOS, Windows Phone and Java ME cell phones. It is fully functional and does what you need and has the MIT License.

The Android project within GpsTracker uses the new Google Play services and there are also two server stacks (ASP.NET and PHP) to allow you to track those phones.

Blimp answered 28/1, 2014 at 3:42 Comment(1)
THe problem is that not all devices have Google Play Services, including any custom ROM that isn't pirating it. If you're going to use it, have a fallback to LocationManager ready.Quesenberry
A
3

April 2020

Full steps to get current location, and avoid Last Known Location nullability.

According to official documentation, Last Known Location could be Null in case of:

  • Location is turned off in the device settings. As it clears the cache.
  • The device never recorded its location. (New device)
  • Google Play services on the device has restarted.

In this case, you should requestLocationUpdates and receive the new location on the LocationCallback.

By the following steps your last known Location never null.


Pre-requisite: EasyPermission library


Step 1: In manifest file add this permission

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Step 2:

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //Create location callback when it's ready.
    createLocationCallback()

    //createing location request, how mant request would be requested.
    createLocationRequest()

    //Build check request location setting request
    buildLocationSettingsRequest()

    //FusedLocationApiClient which includes location 
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    //Location setting client
    mSettingsClient = LocationServices.getSettingsClient(this)

    //Check if you have ACCESS_FINE_LOCATION permission
    if (!EasyPermissions.hasPermissions(
            this@MainActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)) {
        requestPermissionsRequired()
    }
    else{
        //If you have the permission we should check location is opened or not
        checkLocationIsTurnedOn()
    }

}

Step 3: Create required functions to be called in onCreate()

private fun requestPermissionsRequired() {
    EasyPermissions.requestPermissions(
        this,
        getString(R.string.location_is_required_msg),
        LOCATION_REQUEST,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}

private fun createLocationCallback() {
    //Here the location will be updated, when we could access the location we got result on this callback.
    mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            mCurrentLocation = locationResult.lastLocation
        }
    }
}

private fun buildLocationSettingsRequest() {
    val builder = LocationSettingsRequest.Builder()
    builder.addLocationRequest(mLocationRequest!!)
    mLocationSettingsRequest = builder.build()
    builder.setAlwaysShow(true)
}

private fun createLocationRequest() {
    mLocationRequest = LocationRequest.create()
    mLocationRequest!!.interval = 0
    mLocationRequest!!.fastestInterval = 0
    mLocationRequest!!.numUpdates = 1
    mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
    mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
        .addOnSuccessListener(this) {
            Log.i(TAG, "All location settings are satisfied.")
            startLocationUpdates()
        }
        .addOnFailureListener(this) { e ->
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    try {
                        val rae = e as ResolvableApiException
                        rae.startResolutionForResult(this@MainActivity, LOCATION_IS_OPENED_CODE)
                    } catch (sie: IntentSender.SendIntentException) {
                    }
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    mRequestingLocationUpdates = false
                }
            }
        }
}

private fun startLocationUpdates() {
    mFusedLocationClient!!.requestLocationUpdates(
        mLocationRequest,
        mLocationCallback, null
    )
}

Step 4:

Handle callbacks in onActivityResult() after ensuring the location is opened or the user accepts to open it in.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        LOCATION_IS_OPENED_CODE -> {
            if (resultCode == AppCompatActivity.RESULT_OK) {
                Log.d(TAG, "Location result is OK")
            } else {
                activity?.finish()
            }
        }
}

Step 5: Get last known location from FusedClientApi

override fun onMapReady(map: GoogleMap) {
    mMap = map
    mFusedLocationClient.lastLocation.addOnSuccessListener {
        if(it!=null){
            locateUserInMap(it)
        }
    }

}
   private fun locateUserInMap(location: Location) {
    showLocationSafetyInformation()
    if(mMap!=null){
        val currentLocation = LatLng(location.latitude,location.longitude )
        addMarker(currentLocation)
    }
}


private fun addMarker(currentLocation: LatLng) {
    val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
    mMap?.clear()
    mMap?.addMarker(
        MarkerOptions().position(currentLocation)
            .title("Current Location")
    )
    mMap?.moveCamera(cameraUpdate)
    mMap?.animateCamera(cameraUpdate)
    mMap?.setMinZoomPreference(14.0f);
}

I hope this would help.

Happy Coding 🤓

Aerobatics answered 21/4, 2020 at 11:30 Comment(1)
Thanks for good explanations and EasyPermission library, but see comments to https://mcmap.net/q/55428/-how-can-i-get-my-current-location-in-android-using-gps. They say that fused location provider relies on play services, which google forces you to update often. If you don't, you lose play services which breaks fuse location provider.Temperature
L
2

I have published a small library that can make it easy to get location data in Android, it even takes care of Android M runtime permissions.

You might check it out here: https://github.com/julioromano/RxLocation and use it or its source code as examples for your implementation.

Linolinocut answered 25/10, 2016 at 17:28 Comment(3)
It's a good solution but not the best, doesn't work most of the time. I don't get results instantaneously after clicking the button.Alexandrine
@AsifAli If you find a bug please open an issue or submit a PR.Linolinocut
This library because this library missing a class AbstractSafeParcelableAbstriction
T
2

Simple Find Write Code in On Location Method

public void onLocationChanged(Location location) {
    if (mCurrLocationMarker != null) {
        mCurrLocationMarker.remove();
    }


    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
    mCurrLocationMarker = mMap.addMarker(markerOptions);

    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(18));

    PolylineOptions pOptions = new PolylineOptions()
            .width(5)
            .color(Color.GREEN)
            .geodesic(true);
    for (int z = 0; z < routePoints.size(); z++) {
        LatLng point = routePoints.get(z);
        pOptions.add(point);
    }
    line = mMap.addPolyline(pOptions);
    routePoints.add(latLng);
}
Tablecloth answered 13/1, 2017 at 6:8 Comment(0)
A
2

Edit 2022: Don't use this as that lib has memory leaks and is not support/updated any more.

I will recommend using Smart Location Library
Very simple to use and it wraps the location logic nicely.

For starting the location service:

SmartLocation.with(context).location()
    .start(new OnLocationUpdatedListener() { ... });

If you just want to get a single location (not periodic) you can just use the oneFix modifier. Example:

SmartLocation.with(context).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() { ... });
Araiza answered 10/4, 2018 at 13:24 Comment(2)
is this more robust / smaller size for the library usage or something ?Oatmeal
I would not recommend this anymore.Araiza
F
2

Best way to fetch location is below

// put dependancy
 implementation 'com.google.android.gms:play-services-location:11.0.4'

// PUT permissions in Menifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 


// create a Java file as below

public class SingleShotLocationProvider {

  public static interface LocationCallback {
      public void onNewLocationAvailable(GPSCoordinates location);
  }

   // calls back to calling thread, note this is for low grain: if you want higher precision, swap the
   // contents of the else and if. Also be sure to check gps permission/settings are allowed.
   // call usually takes <10ms

  public static void requestSingleUpdate(final Context context, final LocationCallback callback) {
    final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (isNetworkEnabled) {
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        locationManager.requestSingleUpdate(criteria, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
            }

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

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onProviderDisabled(String provider) {
            }
        }, null);
     } else {
        boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (isGPSEnabled) {
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            locationManager.requestSingleUpdate(criteria, new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
                }

                @Override public void onStatusChanged(String provider, int status, Bundle extras) { }
                @Override public void onProviderEnabled(String provider) { }
                @Override public void onProviderDisabled(String provider) { }
            }, null);
        }
     }
  }


  // consider returning Location instead of this dummy wrapper class
  public static class GPSCoordinates {
     public float longitude = -1;
     public float latitude = -1;

     public GPSCoordinates(float theLatitude, float theLongitude) {
        longitude = theLongitude;
        latitude = theLatitude;
     }

     public GPSCoordinates(double theLatitude, double theLongitude) {
        longitude = (float) theLongitude;
        latitude = (float) theLatitude;
     }
  }

}
// FILE FINISHED


// FETCH LOCATION FROM ACTIVITY AS BELOW
public void getLocation(Context context) {
    MyApplication.log(LOG_TAG, "getLocation() ");

    SingleShotLocationProvider.requestSingleUpdate(context,
            new SingleShotLocationProvider.LocationCallback() {
                @Override
                public void onNewLocationAvailable(SingleShotLocationProvider.GPSCoordinates loc) {
                    location = loc;
                    MyApplication.log(LOG_TAG, "getLocation() LAT: " + location.latitude + ", LON: " + location.longitude);               
                }
            });
}
Fur answered 14/5, 2019 at 9:25 Comment(1)
java.lang.SecurityException: "fused" location provider requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.Driftwood
M
0

you can use this code that only need location permission :

val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager

val locationListener = android.location.LocationListener { location ->
            //TODO you can use location data like lat,lon,altitude, ...
     }

if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            //TODO permission not granted
        } else {
            locationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                0L,
                0F,
                locationListener!!
            )
}
Mane answered 30/5, 2023 at 5:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.