LocationClient getLastLocation () возвращает значение null
как вопросы, с которыми кто-то сталкивался раньше
Я тестировал один Нексус с(4.0.4 с сервиса Google Play доступны) и АВД (4.2.2 с 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) {}
}
большинство из них пришли из примеров, приведенных google. В приведенном выше коде Хава попробовал такой метод:
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(), но все равно не везет.
Где ошибка, спасибо продвижение.
13 ответов:
на
Fused Location Providerбудет поддерживать только фоновое местоположение, если к нему подключен хотя бы один клиент. Как только первый клиент подключится, он сразу же попытается получить местоположение. Если ваша деятельность является первым клиентом для подключения, и вы звонитеgetLastLocation()сразуonConnected(), это может быть недостаточно времени для первого местоположения, чтобы войти.
у меня была такая же проблема при выполнении инструкций от учебник. На телефоне он работал, а на эмуляторе (Genymotion) - нет.
решение
в вашем AndroidManifest.xml, измените это:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />для этого:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />...и вы получите местоположение немедленно. Нет необходимости изменять код (для прослушивания обновлений местоположения).
проблема также может быть вызвана тем, что ваше устройство не имеет "Wi-Fi & mobile network location" включен.
LocationClient (поставщик сплавленного местоположения) использует как GPS, так и WiFi. GPS занимает некоторое время, чтобы найти свое местоположение, в то время как wifi намного быстрее. Однако, если какая-либо из этих 2 служб подключена, будет вызван метод обратного вызова onConnected. И если вы пытаетесь вызвать LocationClient.getLastLocation () в методе onConnected немедленно, скорее всего, что вы получит нулевое значение, если ваша служба определения местоположения wifi отключена. Это просто потому, что GPS просто не достаточно быстро.
чтобы решить проблему для себя локально, включите"Wi-Fi & mobile network location". Вы можете сделать это, перейдя в "настройки > Личные > доступ к местоположению > Wi-Fi и местоположение мобильной сети".
однако, если вы хотите решить эту проблему для пользователей вашего приложения, вам лучше проверить, возвращает ли getLastLocation() null. Если это так, попросите пользователя включить сервис так же, как google map делает.
надеюсь, что помогает.
я столкнулся с аналогичной проблемой.
вызов
mLocationClient.getLastLocation()наonConnectedили после установления соединения с сервисами Google Play. Если вы вызываете этот метод до подключения клиента Location, возвращаемое местоположение будетnull.вы можете проверить, подключен ли клиент местоположения
mLocationClient.isConnected().надеюсь, что это помогает.
вы должны проверить, если пользователь включил местоположение через Wi-Fi/GSM или GPS. Если нет ни одного доступного поставщика местоположения, вы получаете
null.этот код отображает экран с настройками местоположения:
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
это точно рабочее решение, вероятно несколько разных обстоятельствах. Но я хотел бы добавить некоторые небольшие шаги объяснения, так что кто-нибудь получает точные понятия:
1) onCreate () компонента Android (например,активность,фрагмент или сервис. Примечание: Не 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) Теперь, на onlocationchange () обратный вызов интерфейса LocationListener, вы получаете новое местоположение.
@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: Location: Location[fused 37.421998, -122.084000 acc=20 et=+15m35s840ms alt=0.0]
чтобы быть в состоянии сделать эти три шага, вы должны были настроить свою сборку.gradle как показано ниже:
compile 'com.google.android.gms:play-services-location:10.2.1'
я столкнулся с аналогичными проблемами в своих тестах с телефонами Samsung (высоко настроенный android и без поддержки разработчиков).
LocationManager и LocationClient не получают GPS от поставщиков. Они должны быть kickstarted каждый раз, когда вам нужно местоположение от них. Сделайте это перед вашим
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) { } });
на SDK версии 23
Вам также нужно будет явно запрашивать разрешение на размещение во время выполнения, согласно https://developer.android.com/training/permissions/requesting.html а также иметь его в файле манифеста.
явная ошибка не возникает, если у вас нет разрешений во время выполнения, поставщик расположения просто вернет null.
это помогло бы, если бы Google задокументировал это, а также бросил исключение, а не просто возврат null. Возврат null - это наименее полезная вещь в этой ситуации.
Я также столкнулся с той же проблемой в своем приложении, и единственной недостающей вещью было то, что приложение запрашивало только ACCESS_COARSE_LOCATION, а не ACCESS_FINE_LOCATION. Я добавил более позднее разрешение, и все работало нормально.
геолокация сервиса Google play не может работать без подключения к интернету, безразлично для GPS. Итак, пожалуйста, проверьте приложение с мобильными данными включен.
вам просто нужен запрос на обновление местоположения. Если с 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(); }
Я бегу и его работа идеально подходит в устройстве Nexus 7. Вы, ребята, по ошибке написали старую версию LocationListener, которая не используется с новым API.
вы должны установить с новым LocationListener.
вам нужно импортировать этот класс и попробуйте.
import com.google.android.gms.location.LocationListener;и он переопределяет только один метод в соответствии с новым API
@Override public void onLocationChanged(final Location newLocation) {}пожалуйста, попробуйте этот способ и дайте мне знать, если вы все еще сталкиваются с любой вопрос.
спасибо.
самое простое исправление, хотя и замедляет его немного, заключается в использовании вспомогательной функции. Моя проблема заключалась в том, что он подключался, но прежде чем было найдено местоположение, я пытался получить к нему доступ и ударил нулевой указатель.
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.
Comments