如何在Android中获取位置管理器的最后已知位置?

17

我正在使用简单的位置管理器对象来获取设备的lastKnownLocation(),但是返回null对象,有人能告诉我为什么吗?

代码:

public Location getLocation() {
    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);        
    if (locationManager != null) {          
        Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (lastKnownLocationGPS != null) {             
            return lastKnownLocationGPS;
        } else {                
            Location loc =  locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
            System.out.println("1::"+loc);----getting null over here
            System.out.println("2::"+loc.getLatitude());
            return loc;
        }
    } else {            
        return null;
    }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.location);
    getLocation();-----calling service

 }

授予的权限:

 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

那么有没有遗漏的设置吗?我已经检查了设备中的位置服务是开启的 请给出一些可工作示例的链接


2
请遵循最新的文档 http://developer.android.com/training/location/retrieve-current.html#GetLocation :) - Deniz
请查看此链接:http://stackoverflow.com/a/15997304/3020568 - Deniz
@deniz 谢谢,我正在实现您给出的第一个链接。这里获取到的lastLocation是null值。以下是代码:if (mUpdatesRequested) {mLocationClient.requestLocationUpdates(mLocationRequest, this);} - Aditi K
是的,我正在尝试,但仍然没有得到 :( - Aditi K
在OnCreate中,将“getLocation();”更改为“Location theLoc = getLocation();”如果您不将其分配给对象,则返回值毫无意义。 - toto_tata
显示剩余5条评论
9个回答

6

在获取最后位置之前,您可能需要获取当前位置,检查是否为空或已有位置。如果不为空,则设置最后位置,如果要使用FusedLocationProviderClient,则在使用它之前添加以下内容:

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

在您的build.gradle(Module: app)中,并在活动创建时调用zoomMyCuurentLocation()方法。

private void zoomMyCuurentLocation() {
    LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    Criteria criteria = new Criteria();
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    Location location = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, false));
    if (location != null) {
        double lat = location.getLatitude();
        double longi = location.getLongitude();
        LatLng latLng = new LatLng(lat,longi);
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14.f));
        Log.d(TAG, "zoomMyCuurentLocation: location not null");
    } else {
        setMyLastLocation();
    }
}

private void setMyLastLocation() {
    Log.d(TAG, "setMyLastLocation: excecute, and get last location");
    FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    fusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
        @Override
        public void onSuccess(Location location) {
            if (location != null){
                double lat = location.getLatitude();
                double longi = location.getLongitude();
                LatLng latLng = new LatLng(lat,longi);
                Log.d(TAG, "MyLastLocation coordinat :"+latLng);
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14.f));
            }
        }
    });
}

4

关于这个问题,可能会有一个笨拙的答案……我重新启动了设备之后,问题得到了解决。请确保您的位置服务已启用并正常工作。


3
我用来获取地点名称的位置信息工具是:
GPSTracker gpsTracker = new GPSTracker(CameraActivity.this);
String stringLatitude = "", stringLongitude = "", nameOfLocation="";
    if (gpsTracker.canGetLocation()) {
        stringLatitude = String.valueOf(gpsTracker.latitude);
        stringLongitude = String.valueOf(gpsTracker.longitude);
        nameOfLocation = ConvertPointToLocation(stringLatitude,stringLongitude);
    }

public String ConvertPointToLocation(String Latitude, String Longitude) {
    String address = "";
    Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
    try {
        List<Address> addresses = geoCoder.getFromLocation(
                Float.parseFloat(Latitude), Float.parseFloat(Longitude), 1);

        if (addresses.size() > 0) {
            for (int index = 0; index < addresses.get(0)
                    .getMaxAddressLineIndex(); index++)
                address += addresses.get(0).getAddressLine(index) + " ";
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return address;
}


GPSTracker.java

package in.appology.lss;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

/**
 * Create this Class from tutorial :
 * http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial
 * 
 * For Geocoder read this :
 * https://dev59.com/1XRB5IYBdhLWcg3w6LR2
 * -geocoding-getfromlocation
 * 
 */

public class GPSTracker extends Service implements LocationListener {
private final Context mContext;

// flag for GPS Status
boolean isGPSEnabled = false;

// flag for network status
boolean isNetworkEnabled = false;

boolean canGetLocation = false;

Location location;
double latitude;
double longitude;

// The minimum distance to change updates in metters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10
                                                                // metters

// The minimum time beetwen updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

// Declaring a Location Manager
protected LocationManager locationManager;

public GPSTracker(Context context) {
    this.mContext = context;
    getLocation();
}

public Location getLocation() {
    try {
        locationManager = (LocationManager) mContext
                .getSystemService(LOCATION_SERVICE);

        // getting GPS status
        isGPSEnabled = locationManager
                .isProviderEnabled(LocationManager.GPS_PROVIDER);

        // getting network status
        isNetworkEnabled = locationManager
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            // no network provider is enabled
        } else {
            this.canGetLocation = true;

            // First get location from Network Provider
            if (isNetworkEnabled) {
                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,
                        MIN_TIME_BW_UPDATES,
                        MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                Log.d("Network", "Network");

                if (locationManager != null) {
                    location = locationManager
                            .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    updateGPSCoordinates();
                }
            }

            // if GPS Enabled get lat/long using GPS Services
            if (isGPSEnabled) {
                if (location == null) {
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    Log.d("GPS Enabled", "GPS Enabled");

                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        updateGPSCoordinates();
                    }
                }
            }
        }
    } catch (Exception e) {
        // e.printStackTrace();
        Log.e("Error : Location",
                "Impossible to connect to LocationManager", e);
    }

    return location;
}

public void updateGPSCoordinates() {
    if (location != null) {
        latitude = location.getLatitude();
        longitude = location.getLongitude();
    }
}

/**
 * Stop using GPS listener Calling this function will stop using GPS in your
 * app
 */

public void stopUsingGPS() {
    if (locationManager != null) {
        locationManager.removeUpdates(GPSTracker.this);
    }
}

/**
 * Function to get latitude
 */
public double getLatitude() {
    if (location != null) {
        latitude = location.getLatitude();
    }

    return latitude;
}

/**
 * Function to get longitude
 */
public double getLongitude() {
    if (location != null) {
        longitude = location.getLongitude();
    }

    return longitude;
}

/**
 * Function to check GPS/wifi enabled
 */
public boolean canGetLocation() {
    return this.canGetLocation;
}

/**
 * Function to show settings alert dialog
 */
public void showSettingsAlert() {
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

    // Setting Dialog Title
    alertDialog.setTitle("GPS");

    // Setting Dialog Message
    alertDialog
            .setMessage("Please enable location in settings for accurate results!");

    // On Pressing Setting button
    alertDialog.setPositiveButton("Settings",
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent(
                            Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    mContext.startActivity(intent);
                }
            });

    // On pressing cancel button
    alertDialog.setNegativeButton("Cancel",
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });

    alertDialog.show();
}

/**
 * Get list of address by latitude and longitude
 * 
 * @return null or List<Address>
 */
public List<Address> getGeocoderAddress(Context context) {
    if (location != null) {
        Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
        try {
            List<Address> addresses = geocoder.getFromLocation(latitude,
                    longitude, 1);
            return addresses;
        } catch (IOException e) {
            // e.printStackTrace();
            Log.e("Error : Geocoder", "Impossible to connect to Geocoder",
                    e);
        }
    }

    return null;
}

/**
 * Try to get AddressLine
 * 
 * @return null or addressLine
 */
public String getAddressLine(Context context) {
    List<Address> addresses = getGeocoderAddress(context);
    if (addresses != null && addresses.size() > 0) {
        Address address = addresses.get(0);
        String addressLine = address.getAddressLine(0);

        return addressLine;
    } else {
        return null;
    }
}

/**
 * Try to get Locality
 * 
 * @return null or locality
 */
public String getLocality(Context context) {
    List<Address> addresses = getGeocoderAddress(context);
    if (addresses != null && addresses.size() > 0) {
        Address address = addresses.get(0);
        String locality = address.getLocality();

        return locality;
    } else {
        return null;
    }
}

/**
 * Try to get Postal Code
 * 
 * @return null or postalCode
 */
public String getPostalCode(Context context) {
    List<Address> addresses = getGeocoderAddress(context);
    if (addresses != null && addresses.size() > 0) {
        Address address = addresses.get(0);
        String postalCode = address.getPostalCode();

        return postalCode;
    } else {
        return null;
    }
}

/**
 * Try to get CountryName
 * 
 * @return null or postalCode
 */
public String getCountryName(Context context) {
    List<Address> addresses = getGeocoderAddress(context);
    if (addresses != null && addresses.size() > 0) {
        Address address = addresses.get(0);
        String countryName = address.getCountryName();

        return countryName;
    } else {
        return null;
    }
}

@Override
public void onLocationChanged(Location location) {
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onProviderEnabled(String provider) {
}

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

@Override
public IBinder onBind(Intent intent) {
    return null;
}
}

1
我将使用GooglePlayLocation服务代替GPS。 - Aditi K
它正在运行一个用于获取位置的服务。提问者从未提到过特定间隔的位置报告。不适合所提出的问题。 - Abhinav Arora

3

我发现的最佳方法:

private Location getLastKnownLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return null;
    }

    List<String> providers = locationManager.getProviders(true);
    Location bestLocation = null;
    for (String provider : providers) {
        Location l = locationManager.getLastKnownLocation(provider);
        if (l == null) {
            continue;
        }
        if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
            // Found best last known location:
            bestLocation = l;
        }
    }

    return bestLocation;
}

locationManager变量可以通过系统服务LOCATION获得。


缺失:在List<String> providers之前,需要添加以下代码:LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - Luke Dupin

3

要获取最后一次位置,可以参考上面提供的答案,使用Location Manager或FusedLocationClient。

但您也可以使用比其他方法更快的LocationServices

因此,让我简要介绍一下如何操作:

1)在gradle app文件中添加这两个依赖项

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

2)将这些权限添加到manifest文件的application标签外部

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

3) 在onCreate外声明变量

private FusedLocationProviderClient fusedLocationClient;

4) 现在在 onCreate 方法中添加:

fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();

5) 没有定义 fetchLastLocation 方法

private void fetchLastLocation() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    Activity#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 Activity#requestPermissions for more details.
//                    Toast.makeText(MainActivity.this, "Permission not granted, Kindly allow permission", Toast.LENGTH_LONG).show();
                showPermissionAlert();
                return;
            }
        }
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        // Got last known location. In some rare situations this can be null.
                        if (location != null) {
                            // Logic to handle location object
                            Log.e("LAST LOCATION: ", location.toString());
                        }
                    }
                });

    }

6) 现在定义另外两个方法以请求权限

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 123: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                    // permission was denied, show alert to explain permission
                    showPermissionAlert();
                }else{
                    //permission is granted now start a background service
                    if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                            && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        fetchLastLocation();
                    }
                }
            }
        }
    }

    private void showPermissionAlert(){
        if (ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainHomeActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 123);
        }
    }

注意: 用你的类上下文替换context

你将在Logcat中获得你的位置。

希望这对你或其他人有所帮助。


2
            // Get the location from the given provider
            Location location = locationManager
                    .getLastKnownLocation(provider);

            locationManager.requestLocationUpdates(provider, 1000, 1, this);

1
在 Kotlin 中解决问题: 抱歉排版很糟糕。
  1. Add these two dependencies in your gradle app file

     implementation 'com.google.android.gms:play-services-maps:17.0.0'
     implementation 'com.google.android.gms:play-services-location:17.0.0'
    
  2. Add these permissions in the manifest file outside applicationtag

     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
  3. Declare variable outside onCreate

     private lateinit var fusedLocationClient: FusedLocationProviderClient
    
  4. Now inside onCreate :

     fusedLocationClient= LocationServices.getFusedLocationProviderClient(this)
    
     getCurrentLocation()
    
  5. No define fetchLastLocation method Note:Here getCurrentLocation means the last location.

     private fun getCurrentLocation(){
     if(checkPermissions())
     {
         if(isLocationEnabled()){
             //final latitude and longitude
             if (ActivityCompat.checkSelfPermission(
                     this,
                     Manifest.permission.ACCESS_FINE_LOCATION
                 ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                     this,
                     Manifest.permission.ACCESS_COARSE_LOCATION
                 ) != PackageManager.PERMISSION_GRANTED
             ) {
                 requestPermission()
                 return
             }
             // fusedLocationClient.getCurrentLocation()
             fusedLocationClient.lastLocation.addOnCompleteListener(this){ task->
                 val location:Location?=task.result
                 if(location==null)
                 {
                     Toast.makeText(this,"NULL Received",Toast.LENGTH_SHORT).show()
                 }
                 else{
                     Toast.makeText(this,"Location SUCCESS",Toast.LENGTH_SHORT).show()
                     val geocoder = Geocoder(this, Locale.getDefault())
                     val addresses: MutableList<android.location.Address>? = geocoder.getFromLocation(location.latitude, location.longitude, 1)
                     cityName = addresses!![0].locality
                     startActivity(intent)
                 }
             }
         }
         else
         {
             Toast.makeText(this,"Turn on location",Toast.LENGTH_SHORT).show()
             val intent= Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
             startActivity(intent)
         }
     }
     else
     {
         //request permission here
         requestPermission()
     }
    

    }

  6. Now define other methods for permission request

     private fun requestPermission() {
     ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION,android.Manifest.permission.ACCESS_FINE_LOCATION),
         PERMISSION_REQUEST_ACCESS_LOCATION)
     }
    
     companion object{
     private const val PERMISSION_REQUEST_ACCESS_LOCATION=100
     }
    
     private fun checkPermissions():Boolean {
     if (ActivityCompat.checkSelfPermission(
             this,
             android.Manifest.permission.ACCESS_FINE_LOCATION
         ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
             this,
             android.Manifest.permission.ACCESS_COARSE_LOCATION
         ) == PackageManager.PERMISSION_GRANTED
     ) {
         return true
     }
     return false
     }
    
     override fun onRequestPermissionsResult(
     requestCode: Int,
     permissions: Array<out String>,
     grantResults: IntArray
     ) {
     super.onRequestPermissionsResult(requestCode, permissions, grantResults)
     if(requestCode== PERMISSION_REQUEST_ACCESS_LOCATION)
     {
         if(grantResults.isNotEmpty() && grantResults[0]==PackageManager.PERMISSION_GRANTED){
             Toast.makeText(applicationContext,"Granted",Toast.LENGTH_SHORT).show()
             getCurrentLocation()
         }
         else{
             Toast.makeText(applicationContext,"DENIED",Toast.LENGTH_SHORT).show()
         }
     }
     }
    
     private fun isLocationEnabled():Boolean{
     val locationManager:LocationManager=getSystemService(Context.LOCATION_SERVICE) as LocationManager
     return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)||locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
     }
    

1
以下是我尝试获取最后位置的方法。
private void setUpMap(){
    //Location location = mMap.getMyLocation();
    mMap.setMyLocationEnabled(true);
    //mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
        @Override
        public void onMyLocationChange(Location location) {
             mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())).title("My Location"));
             mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),10));
             mMap.setOnMyLocationChangeListener(null);
        }
    });
}

0

这里有一个更好的解决方案:

@Nullable
public static Location getLastKnownLocation(Context context, LocationManager locationManager) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return null;
    }

    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);

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

    return locationManager.getLastKnownLocation(provider);
}

这一行代码:criteria.setAccuracy(Criteria.ACCURACY_FINE); 就可以达到效果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接