就像之前遇到的问题一样
我测试了一个nexus s(4.0.4提供谷歌播放服务)和avd(4.2.2 with google api),在这两种情况下,locationclient getLastLocation()
总是返回null
。
public class MainActivity extends Activity implements LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
boolean mUpdatesRequested = false;
boolean mConnected = false;
SharedPreferences mPrefs;
SharedPreferences.Editor mEditor;
private TextView mText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = (TextView) findViewById(R.id.text);
mLocationRequest = LocationRequest.create();
mLocationRequest
.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest
.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
mUpdatesRequested = false;
mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES,
Context.MODE_PRIVATE);
mEditor = mPrefs.edit();
mLocationClient = new LocationClient(this, this, this);
}
@Override
public void onStart() {
super.onStart();
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
mLocationClient.connect();
}
@Override
protected void onResume() {
super.onResume();
// If the app already has a setting for getting location updates, get it
if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
mUpdatesRequested = mPrefs.getBoolean(
LocationUtils.KEY_UPDATES_REQUESTED, false);
// Otherwise, turn off location updates until requested
} else {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
mEditor.commit();
}
}
@Override
public void onStop() {
// If the client is connected
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
// After disconnect() is called, the client is considered "dead".
mLocationClient.disconnect();
super.onStop();
}
@Override
public void onPause() {
// Save the current setting for updates
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED,
mUpdatesRequested);
mEditor.commit();
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void getLocation(View v) {
// If Google Play Services is available
if (isGooglePlayServicesAvailable()) {
if (!mConnected)
mText.setText("location client is not connected to service yet");
else {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Display the current location in the UI
mText.setText(LocationUtils.getLocationString(currentLocation));
}
}
}
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG, "google play service is available");
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode,
this, 0);
if (dialog != null) {
Log.e(LocationUtils.APPTAG,
"google play service is unavailable");
}
return false;
}
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
// mConnectionState.setText(R.string.location_updates_stopped);
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
mConnected = false;
Log.d(LocationUtils.APPTAG, "connection failed");
}
@Override
public void onConnected(Bundle arg0) {
mConnected = true;
Log.d(LocationUtils.APPTAG,
"location client connected to the location server");
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
new android.location.LocationListener() {
@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 onLocationChanged(final Location location) {
}
});
Log.d(LocationUtils.APPTAG, "done trying to get location");
}
@Override
public void onDisconnected() {
// TODO Auto-generated method stub
mConnected = false;
Log.d(LocationUtils.APPTAG,
"location client disconnected from the location server");
}
@Override
public void onLocationChanged(Location arg0) {}
}
其中大多数来自谷歌提供的示例。在上面的代码中,hava尝试了这样的方法:
LocationRequest request = LocationRequest.create();
request.setNumUpdates(1);
mLocationClient.requestLocationUpdates(request, this);
和
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
new android.location.LocationListener() {
@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 onLocationChanged(final Location location) {}
});
在调用onConnected()
之前getLastLocation()
,但仍然没有运气。
哪里是错误,提前谢谢。
答案 0 :(得分:50)
目前Fused Location Provider
仅在至少有一个客户端连接到它时才会维护后台位置。一旦第一个客户端连接,它将立即尝试获取位置。如果您的活动是第一个要连接的客户,并且您在getLastLocation()
中立即致电onConnected()
,则可能没有足够的时间让第一个地点进入。
答案 1 :(得分:21)
按照the tutorial的说明操作时遇到同样的问题。 在手机上它工作,并在(Genymotion)模拟器它没有。
在AndroidManifest.xml中,更改此内容:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
到此:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
......然后你马上就到了。无需更改代码(收听位置更新)。
答案 2 :(得分:19)
您的设备未启用“Wi-Fi和移动网络位置”也可能导致此问题。
LocationClient(融合位置提供商)使用GPS和WiFi。 GPS需要一段时间才能找到您的位置,而wifi速度要快得多。但是,如果连接了这两个服务中的任何一个,则将调用onConnected的回调方法。如果您尝试立即在onConnected方法中调用LocationClient.getLastLocation(),那么如果您的wifi位置服务被禁用,则很可能会获得空值。这只是因为GPS不够快。
要在本地解决此问题,请启用“Wi-Fi和移动网络位置”。您可以转到“设置&gt;个人&gt;位置访问&gt; Wi-Fi和移动网络位置”来执行此操作。
但是,如果要解决应用程序用户的问题,最好检查getLastLocation()是否返回null。如果是,请提示您的用户启用该服务,就像谷歌地图一样。
希望这有帮助。
答案 3 :(得分:7)
我遇到了类似的问题。
在mLocationClient.getLastLocation()
中或在建立与Google Play服务的连接后致电onConnected
。如果您在连接位置客户端之前调用此方法,则返回的位置将为null
。
您可以通过mLocationClient.isConnected()
检查位置客户端是否已连接。
希望这有帮助。
答案 4 :(得分:5)
您必须检查用户是否通过Wi-Fi / GSM或GPS启用了位置。如果没有任何可用的位置提供商,则会获得null
。
此代码显示包含位置设置的屏幕:
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
答案 5 :(得分:5)
这是完全有效的解决方案,可能在不同的情况下。但我想添加一些解释步骤,以便任何人都能获得确切的概念:
1)Android组件的onCreate()(例如,活动,片段或服务。注意:不是IntentService ),构建,然后连接 GoogleApiClient,如下所示。
buildGoogleApiClient();
mGoogleApiClient.connect();
其中,buildGoogleApiClient()实现是,
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
稍后在onDestroy()上,您可以将GoogleApiClient与
断开连接@Override
public void onDestroy() {
Log.i(TAG, "Service destroyed!");
mGoogleApiClient.disconnect();
super.onDestroy();
}
第1步确保您构建并连接GoogleApiClient。
1)GoogleApiClient实例第一次在方法onConnected()上连接。现在,您的下一步应该是onConnected()方法。
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.i(TAG, "GoogleApiClient connected!");
buildLocationSettingsRequest();
createLocationRequest();
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Log.i(TAG, " Location: " + location); //may return **null** because, I can't guarantee location has been changed immmediately
}
上面,您调用方法 createLocationRequest()来创建位置请求。方法 createLocationRequest()如下所示。
protected void createLocationRequest() {
//remove location updates so that it resets
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); //Import should not be **android.Location.LocationListener**
//import should be **import com.google.android.gms.location.LocationListener**;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//restart location updates with the new interval
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
3)现在,在LocationListener接口的onLocationChange()回调中,您将获得新位置。
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Location Changed!");
Log.i(TAG, " Location: " + location); //I guarantee,I get the changed location here
}
您可以在Logcat中获得如下结果: 03-22 18:34:17.336 817-817 / com.LiveEarthquakesAlerts I / LocationTracker:位置:位置[fuse 37.421998,-122.084000 acc = 20 et = + 15m35s840ms alt = 0.0]
为了能够执行这三个步骤,您应该已经配置了build.gradle,如下所示:
compile 'com.google.android.gms:play-services-location:10.2.1'
答案 6 :(得分:4)
我在使用三星手机(高度自定义的Android,没有开发人员支持)的测试中遇到了类似的问题。
LocationManager和LocationClient不会从提供商那里获得GPS。每当您需要它们的位置时,它们都需要启动。在LocationManager.getLastKnownLocation
或LocationClient.getLastLocation
来电之前执行此操作。这些API将返回。
YOUR_APPLICATION_CONTEXT.getLocationManager().requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, new LocationListener() {
@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 onLocationChanged(final Location location) {
}
});
答案 7 :(得分:3)
您还需要在运行时明确请求位置权限 https://developer.android.com/training/permissions/requesting.html 以及将它放在清单文件中。
如果您在运行时没有权限,则不会发生显式错误,位置提供程序将只返回null。
如果Google记录了这一点,它会有所帮助,并且还会抛出异常,而不仅仅是返回null。在这种情况下,返回null是最不利的事情。
答案 8 :(得分:2)
我的应用程序也遇到了同样的问题,唯一缺少的是应用程序只请求了ACCESS_COARSE_LOCATION而不是ACCESS_FINE_LOCATION。 我添加了后来的权限,一切正常。
答案 9 :(得分:0)
谷歌播放服务地理定位无法在没有互联网连接的情况下工作,对GPS无动于衷。因此,请检查打开移动数据的应用。
答案 10 :(得分:0)
您只需要该位置的更新请求。如果有26个Android SDK权限就可以了:
private void setLocation(Context context) {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(2000);
locationRequest.setFastestInterval(2000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
showMessage(" All location settings are satisfied.");
mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(connectionFailedListener)
.build();
mGoogleApiClient.connect();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
l.a(" Location settings are not satisfied. Show the user a dialog to upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
showMessage("PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
showMessage("Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
并在onConnected回调方法中:
@Override
public void onConnected(@Nullable Bundle bundle) {
l.a(3232);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if(null==mLastLocation){// !!!!!!!!!!!! here it can happen !!!!!!!
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
locationWasFound = true;
sevumPora.setLocation(mLastLocation);
mGoogleApiClient.disconnect();
}
});
return;
}
locationWasFound = true;
sevumPora.setLocation(mLastLocation);
mGoogleApiClient.disconnect();
}
答案 11 :(得分:-1)
我在Nexus 7设备上运行并完美运行。 你们错误地写了旧版本的LocationListener,它没有用于新的API。
您必须使用新的LocationListener进行设置。
您需要导入此类,然后尝试。
import com.google.android.gms.location.LocationListener;
它根据新API覆盖了唯一一种方法
@Override
public void onLocationChanged(final Location newLocation)
{}
请尝试这种方式,如果您仍然遇到任何问题,请告诉我。
感谢。
答案 12 :(得分:-3)
最简单的解决办法,虽然减慢了一点,但是使用辅助函数。我的问题是它会连接,但在找到一个位置之前,我会尝试访问它并点击一个空指针。
public Location getLocation(LocationClient locationClient){
if(locationClient.getLastLocation() == null){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getLocation(locationClient);
}else{
return locationClient.getLastLocation();
}
}
只需在onConnected
中使用此功能,并设置您想要使用此功能的位置,并传递您的位置客户端。
@Override
public void onConnected(Bundle dataBundle) {
Location temp = getLocation(mLocationClient);
mLocation = temp;
}
此外,如果您因某种原因不想从onConnected
获取位置,只要您通过locationClient
,就可以在任何地方使用相同的辅助功能。