GetLastLocation 始终为空

我想简单地在我的 Android 项目中检索设备的位置,为了这样做,我使用了 play-services 方法:

    protected synchronized void buildGoogleApiClient() {


mGoogleApiClient = new GoogleApiClient.Builder( MainSearchActivity.this )
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected( Bundle bundle ){
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( location == null ){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
}
});
}
}
@Override
public void onConnectionSuspended( int i ){


}


})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed( ConnectionResult connectionResult ){
if( connectionResult.hasResolution() ){
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(MainSearchActivity.this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
}catch( IntentSender.SendIntentException e ){
e.printStackTrace();
}
}else{
Utils.logger("Location services connection failed with code " + connectionResult.getErrorCode(), Utils.LOG_DEBUG );
}
}
})
.addApi(LocationServices.API)
.build();


mGoogleApiClient.connect();
}


public Location retrieveLastLocation(){
Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( loc == null)
{


}
return loc; //TODO: What if loc is null?
}

loc变量始终为空。每次都是在不同的手机上。还有 lastLocation,我尝试在 onLocationChanged中分配,从不改变。总是无效。

这些是我为应用程序设置的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

我只是不明白: 为什么 LocationServices不能恢复一个位置?我在三台测试设备上都启用了所有的地理定位设置。

87561 次浏览

融合后的 Location Provider只有在至少有一个客户端连接到它的情况下才能保持后台位置。现在仅仅打开定位服务并不能保证存储最后已知的位置。

一旦第一个客户端连接上,它将立即尝试获取一个位置。如果您的活动是第一个连接的客户机,并且在 onConnected()中立即调用了 getLastLocation(),那么可能没有足够的时间让第一个位置到达。.

我建议您先启动地图应用程序,以便至少有一些确定的位置,然后测试您的应用程序。

我认为有一个小的错误,这是不可见的,我在代码中显示。

构建了 mGoogleApiClient,但似乎没有连接。您可以通过调用 mGoogleApiClient.isConnected()来验证这一点。

您可以重写 onStart 方法并在那里调用 connect。或者您可以覆盖 onResume(),以便在您的活动可见时访问该位置。

  @Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}

如果 getLastLocation ()总是返回 null,请尝试这种方法。我用它来解决我的问题。实现 LocationListener (import com.google.android.gms.location。位置监听器)。

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);


Context mContext = this;


manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);


createLocationRequest();


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


}


private void createLocationRequest(){
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(SET_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}

OnStart 或 onResume (我更喜欢 onResume)

@Override
protected void onResume() {
super.onResume();
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) ) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}else{
// Showyourmesg();
}
}


@Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
}


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


protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}

现在,在 onLocationChanged 方法中检查 googleApiClient 是否已连接。如果已连接,请断开连接,然后再连接。

@Override
public void onLocationChanged(Location location) {
Log.d("SplashAct", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());


if (mGoogleApiClient != null)
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()){
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
} else if (!mGoogleApiClient.isConnected()){
mGoogleApiClient.connect();
}
}

最后,在 onConnected ()方法中

@Override
public void onConnected(Bundle bundle) {


Log.d("ACTIVITY", "ApiClient: OnConnected");


mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);


if (mLastLocation == null){
startLocationUpdates(); // bind interface if your are not getting the lastlocation. or bind as per your requirement.
}


if (mLastLocation != null){
while (latitude == 0 || longitude == 0){
pDialog.setMessage("Getting Location");
pDialog.show();


latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();


if (latitude != 0 && longitude != 0){
stopLocationUpdates(); // unbind the locationlistner here or wherever you want as per your requirement.
pDialog.dismiss(); // location data received, dismiss dialog, call your method or perform your task.
}
}
}
}

我们反复尝试连接到 googleApiClient,即使它已经连接了,这样我们就可以获得 lastLocation 数据。这将取决于 LocationRequest 间隔。您也可以在 onLocationChanged 中获取位置数据,并从那里执行任务。

这与阿米特 · K · 萨哈的答案有关,但对我来说,在我的一台 Lollipop设备上,我一直得到 null。所以我打开了地图应用程序,我得到了下面的屏幕,要求我打开所有的爵士乐,以改善我的位置。

一旦我这样做了一次,我的设备能够接收的位置,只需要一个电话的 getLastLocation();

我推测,那么一个将不得不要求这些权限的应用程序安装的用户谁可能还没有使用他们的地图应用程序。

enter image description here

首先,创建一个 LocationRequest对象:

 // Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000)        // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds

然后,确保用户已授予使用 location 的权限:

void getLocation() {
Location location = null;
if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);


/*TODO!! INSERT CODE TO PROMPT USER TO GIVE PERMISSION*/


} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}


mLastLocation = location;
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}

如果您只需要一个不需要持续监视的位置,请确保删除更新。这样,您将永远不会得到一个空 Location

欲了解更多信息,请访问 http://blog.teamtreehouse.com/beginners-guide-location-android

如果您正在使用 Android M(API 23)或更新版本的 Android,您可能会面临同样的问题,因为 不授予许可。您应该显式地 在运行时请求权限的位置,或者,如果它是一个测试项目,您可以在您的手机上 授予应用程序设置的位置权限

下面是确切的答案和解释。

LocationClient getLastLocation ()返回 null

正如在 这个后说,融合位置提供商将只维护后台位置,如果至少有一个客户端连接到它。

但是我们可以跳过启动谷歌地图应用程序的过程,通过以下方式获得最后的位置。

我们要做的是

  1. 我们必须从 FusedLocationProviderClient请求位置更新
  2. 然后我们可以从 FusedLocationProviderClient得到最后一个位置,它不会是空的。

请求位置

LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
if (location != null) {
//TODO: UI updates.
}
}
}
};
LocationServices.getFusedLocationProviderClient(context).requestLocationUpdates(mLocationRequest, mLocationCallback, null);

找到最后的位置

LocationServices.getFusedLocationProviderClient(context).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
//TODO: UI updates.
}
});

为了获得最佳结果,请在活动的 onStart ()中更新 requestLocationUpdate,然后您可以获得最后一个位置。

我正在使用下面的代码获取位置根据最新的文档的 android Https://developer.android.com/training/location/retrieve-current

MainActivity.java

public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CHECK_SETTINGS = 1;
private static final int REQUEST_GRANT_PERMISSION = 2;
private FusedLocationProviderClient fusedLocationClient;
LocationRequest locationRequest;
private Location currentLocation;
private LocationCallback locationCallback;
Button getUpdates,removeUpdates;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
createLocationRequest();
settingsCheck();
getUpdates = findViewById(R.id.button);
removeUpdates = findViewById(R.id.button2);


getUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback==null)
buildLocationCallback();
if(currentLocation==null)
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
}
});
removeUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback!=null)
fusedLocationClient.removeLocationUpdates(locationCallback);
}
});
}


protected void createLocationRequest() {
locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}


// Check for location settings
public void settingsCheck() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);


SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
Log.d("TAG", "onSuccess: settingsCheck");
getCurrentLocation();
}
});


task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
Log.d("TAG", "onFailure: settingsCheck");
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}


public void getCurrentLocation(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
Log.d("TAG", "onSuccess: getLastLocation");
// Got last known location. In some rare situations this can be null.
if (location != null) {
currentLocation=location;
Log.d("TAG", "onSuccess:latitude "+location.getLatitude());
Log.d("TAG", "onSuccess:longitude "+location.getLongitude());
}else{
Log.d("TAG", "location is null");
buildLocationCallback();
}
}
});
}


private void buildLocationCallback() {
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
currentLocation=location;
Log.d("TAG", "onLocationResult: "+currentLocation.getLatitude());
}
};
};
}


//called after user responds to location permission popup
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==REQUEST_GRANT_PERMISSION){
getCurrentLocation();
}
}
//called after user responds to location settings popup
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TAG", "onActivityResult: ");
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_OK)
getCurrentLocation();
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_CANCELED)
Toast.makeText(this, "Please enable Location settings...!!!", Toast.LENGTH_SHORT).show();
}}

XML 文件

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.locationexample.MainActivity">


<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="88dp"
android:text="getLocationUpdates"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />


<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="RemoveLocationUpdates"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintVertical_bias="0.363" /</android.support.constraint.ConstraintLayout>

清单档案

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.locationexample">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />


<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

要发出单个位置请求,可以使用

方法1-> getCurrentLocation()

cancellationTokenSource = CancellationTokenSource()


val currentLocationTask = LocationServices
.getFusedLocationProviderClient(requireContext()).getCurrentLocation(
LocationRequest.PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.token
)

您可以使用,

cancellationTokenSource.cancel()

方法2-> setNumUpdates(1)

mLocationRequest
.setNumUpdates(1)

我得到零的位置,我发现地图应用程序没有安装在模拟器上。我安装并启用了设备位置,然后问题解决了

我安装了一个模拟器,有谷歌播放服务和工作

仿生人科特林

如果你需要得到 安卓系统中的用户位置,我正在使用我的 函数 建议它:

// Get user location after getting permission.
private fun findUserLocation() {


if (ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Check location permission. Some one is missing.
}
else {
val locationRequest = LocationRequest.create() // Create location request.
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Set priority.


val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations) {
if (location != null) {


// TODO: Show your code here.
// Such as:
val lat = location.latitude
val lon = location.longitude
}
}
}
}


// Create a location provider client and send request for getting location.
val client = LocationServices.getFusedLocationProviderClient(requireContext())
client.requestLocationUpdates(locationRequest, locationCallback, null)
}
}