get the current location fast and once in android

前端 未结 7 1571
刺人心
刺人心 2020-12-07 10:48

I have an android application that need device current location (latitude and longitude). I\'ve tried some tutorial on the net and specially some solutions from stack overfl

相关标签:
7条回答
  • 2020-12-07 11:22
        // Get LocationManager object
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    
        // Create a criteria object to retrieve provider
        Criteria criteria = new Criteria();
    
        // Get the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);
    
        // Get Current Location
        Location myLocation = locationManager.getLastKnownLocation(provider);
    
        //latitude of location
        double myLatitude = myLocation.getLatitude();
    
        //longitude og location
        double myLongitude = myLocation.getLongitude();
    
        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;
        }
    
    0 讨论(0)
  • 2020-12-07 11:27

    All the above answers are not worked for me so I answered this Initially add the dependencies

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />
    

    after add the class MyLocationListiner.java

    package com.example.firebase_auth;
    
    /**
     * Created by Chromicle(Ajay Prabhakar).
     */
    
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Build;
    import android.os.Bundle;
    import android.widget.Toast;
    
    import androidx.annotation.Nullable;
    import androidx.core.content.ContextCompat;
    
    import static android.content.Context.LOCATION_SERVICE;
    
    public class MyLocationListener implements LocationListener {
    
        public static double latitude;
        Context ctx;
        Location location;
        LocationManager locationManager;
        boolean isGPSEnabled = false;
        boolean isNetworkEnabled = false;
        public static double longitude;
        MyLocationListener(Context ctx) {
            this.ctx = ctx;
            try {
                locationManager = (LocationManager) ctx.getSystemService(LOCATION_SERVICE);
                isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
                Toast.makeText(ctx, "GPS Enable " + isGPSEnabled, Toast.LENGTH_LONG).show();
                isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
                Toast.makeText(ctx, "Network Enable " + isNetworkEnabled, Toast.LENGTH_LONG).show();
    
                if ( Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission
                        ( ctx, android.Manifest.permission.ACCESS_FINE_LOCATION )
                        != PackageManager.PERMISSION_GRANTED &&
                        ContextCompat.checkSelfPermission( ctx,
                                android.Manifest.permission.ACCESS_COARSE_LOCATION) !=
                                PackageManager.PERMISSION_GRANTED) {  }
                if (isGPSEnabled == true) {
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,     0,       0, this);
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                }
                if (isNetworkEnabled==true) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,    0,     0, this);
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                }
                latitude = location.getLatitude();
                longitude = location.getLongitude();
                // Toast.makeText(ctx,"latitude: "+latitude+" longitude: "+longitude,Toast.LENGTH_LONG).show();
    
    
            }
            catch(Exception ex)
            {
    
                Toast.makeText(ctx,"Exception "+ex, Toast.LENGTH_LONG).show();
            }
        }
        @Nullable
        @Override
        public void onLocationChanged(Location loc)
        {
            loc.getLatitude();
            loc.getLongitude();
            latitude=loc.getLatitude();
            longitude=loc.getLongitude();
        }
    
        @Override
        public void onProviderDisabled(String provider)
        {
            //print "Currently GPS is Disabled";
        }
        @Override
        public void onProviderEnabled(String provider)
        {
            //print "GPS got Enabled";
        }
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
    
        }
    }
    

    To use that class add this method location is stored in the Address string

    public void getLocation(){
            Double latitude = 0.0, longitude;
            String message = "";
            LocationManager mlocManager = null;
            LocationListener mlocListener;
            mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            mlocListener = new MyLocationListener(this);
            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;
            }
            mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
            if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    
                latitude = MyLocationListener.latitude;
                longitude = MyLocationListener.longitude;
                message = message +"https://www.google.com/maps/dir/@"+ latitude +","+  longitude;
                address=message;
                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                if (latitude == 0.0) {
                    Toast.makeText(getApplicationContext(), "Currently gps has not found your location....", Toast.LENGTH_LONG).show();
                }
    
            } else {
                Toast.makeText(getApplicationContext(), "GPS is currently off...", Toast.LENGTH_LONG).show();
            }
        }
    

    Hope it helpfull

    0 讨论(0)
  • 2020-12-07 11:38

    Here, you can use this...

    Example usage:

    public void foo(Context context) {
      // when you need location
      // if inside activity context = this;
    
      SingleShotLocationProvider.requestSingleUpdate(context, 
       new SingleShotLocationProvider.LocationCallback() {
         @Override public void onNewLocationAvailable(GPSCoordinates location) {
           Log.d("Location", "my location is " + location.toString());
         }
       });
    }
    

    You might want to verify the lat/long are actual values and not 0 or something. If I remember correctly this shouldn't throw an NPE but you might want to verify that.

    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);
              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;
          }
      }  
    }
    
    0 讨论(0)
  • 2020-12-07 11:38

    AndroidManifest.xml

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />
    

    Requesting User Permissions


    build.gradle (Module: app)

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-location:15.0.0'
        ...
    }
    

    If you receive an error, check that your top-level build.gradle contains a reference to the google() repo or to maven { url "https://maven.google.com" }

    Set Up Google Play Services


    LocationService.kt

    import android.Manifest
    import android.annotation.SuppressLint
    import android.app.Activity
    import android.content.Intent
    import android.content.pm.PackageManager
    import android.location.Location
    import android.net.Uri
    import android.os.Looper
    import android.provider.Settings
    import android.support.v4.app.ActivityCompat
    import android.support.v4.content.ContextCompat
    import com.google.android.gms.common.api.ApiException
    import com.google.android.gms.common.api.ResolvableApiException
    import com.google.android.gms.location.*
    import org.jetbrains.anko.alert
    import org.jetbrains.anko.doAsync
    import org.jetbrains.anko.okButton
    
    object LocationService {
    
        @SuppressLint("StaticFieldLeak")
        private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
        private lateinit var locationRequest: LocationRequest
        private val locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                doAsync {
                    location = locationResult.lastLocation
                    onSuccess(location)
                }
            }
        }
        private lateinit var onSuccess: (location : Location) -> Unit
        private lateinit var onError: () -> Unit
        lateinit var location: Location
    
        fun init(activity: Activity) {
            fusedLocationProviderClient = FusedLocationProviderClient(activity)
            locationRequest = LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000).setFastestInterval(1000).setNumUpdates(1)
        }
    
        private fun checkLocationStatusAndGetLocation(activity: Activity) {
            doAsync {
                when {
                    ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> LocationServices.getSettingsClient(activity).checkLocationSettings(LocationSettingsRequest.Builder().addLocationRequest(locationRequest).setAlwaysShow(true).build()).addOnCompleteListener { task ->
                        doAsync {
                            try {
                                task.getResult(ApiException::class.java)
                                fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
                            } catch (exception: ApiException) {
                                when (exception.statusCode) {
                                    LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                                        try {
                                            (exception as ResolvableApiException).startResolutionForResult(activity, 7025)
                                        } catch (ex: Exception) {
                                            promptShowLocation(activity)
                                        }
                                    }
                                    LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                                        promptShowLocation(activity)
                                    }
                                }
                            }
                        }
                    }
                    ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) -> activity.runOnUiThread {
                        activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") {
                            okButton {
                                val ite = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", activity.packageName, null))
                                ite.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                                activity.startActivity(ite)
                                onError()
                            }
                            negativeButton("Cancelar", { onError() })
                            onCancelled { onError() }
                        }.show()
                    }
                    else -> ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 7024)
                }
            }
        }
    
        private fun promptShowLocation(activity: Activity) {
            activity.runOnUiThread {
                activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") {
                    okButton {
                        activity.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
                        onError()
                    }
                    negativeButton("Cancelar", { onError() })
                    onCancelled { onError() }
                }.show()
            }
        }
    
        fun onRequestPermissionsResult(activity: Activity, requestCode: Int, grantResults: IntArray) {
            if (requestCode == 7024) {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    checkLocationStatusAndGetLocation(activity)
                } else {
                    onError()
                }
            }
        }
    
        fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int) {
            if (requestCode == 7025) {
                if (resultCode == Activity.RESULT_OK) {
                    checkLocationStatusAndGetLocation(activity)
                } else {
                    onError()
                }
            }
        }
    
        fun getLocation(activity: Activity, onSuccess: () -> Unit, onError: () -> Unit) {
            this.onSuccess = onSuccess
            this.onError = onError
            checkLocationStatusAndGetLocation(activity)
        }
    
    }
    

    your activity

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        LocationService.init(this)
    }
    
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        LocationService.onRequestPermissionsResult(this, requestCode, grantResults)
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        LocationService.onActivityResult(this, requestCode, resultCode)
    }
    
    private fun yourFunction() {
        LocationService.getLocation(this, { location ->
            //TODO: use the location
        }, {
            //TODO: display error message
        })
    }
    
    0 讨论(0)
  • 2020-12-07 11:45

    What you want to do is achieved using the LocationManager#requestSingleUpdate. This method attaches a listener in a given looper (if you want or have it) and notifies the location ASAP it is received, only once. The method you suggest is used only as an inexact position before the real one is given to you.

    In any case it will be fast than milliseconds (unless you are lucky enough to start listening when a location came to the device). Think on the GPS as an element that you enable when waiting for locations and disable when you remove this listening. This behavior is done to avoid draining the user's battery.

    So, to sum up:

    • The time between you start listening and you receive the position depends on the device's GPS (manufacture, location of the user, satellite coverage...)
    • There is a method in the Android SDK to listen for a single update.
    • By providing the a criteria object, you can manage which criterias are acceptable for you to receive a location. Stronger criterias means more time to get an accurate response.
    0 讨论(0)
  • 2020-12-07 11:47

    AndroidManifest.xml:

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />
    

    MainActivity.java:

    public class MainActivity extends AppCompatActivity implements LocationListener {
    
        private LocationManager locationManager;
        private Location onlyOneLocation;
        private final int REQUEST_FINE_LOCATION = 1234;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
        }
    
        @Override public void onLocationChanged(Location location) {
            onlyOneLocation = location;
            locationManager.removeUpdates(this);
        }
        @Override public void onStatusChanged(String provider, int status, Bundle extras) { }
        @Override public void onProviderEnabled(String provider) { }
        @Override public void onProviderDisabled(String provider) { }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
            switch (requestCode) {
            case REQUEST_FINE_LOCATION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d("gps", "Location permission granted");
                    try {
                        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                        locationManager.requestLocationUpdates("gps", 0, 0, this);
                    }
                    catch (SecurityException ex) {
                        Log.d("gps", "Location permission did not work!");
                    }
                }
                break;
        }
    }
    
    0 讨论(0)
提交回复
热议问题