Comme les questions que quelqu'un a rencontrées avant de tester l'un des liens (4.0.4 avec le service Google Play disponible) et avd (4.2.2 avec Google Api), dans les deux cas, getLastLocation()
de locationclient renvoie toujours 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) {}
}
la plupart d'entre eux sont issus d'exemples donnés par google. Dans le code ci-dessus, hava a essayé la méthode comme ça:
LocationRequest request = LocationRequest.create();
request.setNumUpdates(1);
mLocationClient.requestLocationUpdates(request, this);
et
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) {}
});
Dans onConnected()
avant d'appeler getLastLocation()
, mais toujours pas de chance. Où est l'erreur, merci d'avance.
Actuellement, le Fused Location Provider
Ne conservera l'emplacement de l'arrière-plan que si au moins un client y est connecté. Une fois le premier client connecté, il essaiera immédiatement d’obtenir un emplacement. Si votre activité est le premier client à se connecter et que vous appelez getLastLocation()
immédiatement dans onConnected()
, le temps imparti au premier emplacement ne sera peut-être pas suffisant.
J'ai eu le même problème en suivant les instructions de le tutoriel . Au téléphone cela a fonctionné et sur l'émulateur (Genymotion) cela n'a pas fonctionné.
Dans votre AndroidManifest.xml, changez ceci:
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
pour ça:
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
... et vous obtenez l'emplacement immédiatement. Pas besoin de changer votre code (pour écouter les mises à jour d'emplacement).
Le problème peut aussi être causé par le fait que votre appareil n'a pas l'option "Emplacement réseau Wi-Fi et mobile" activée.
LocationClient (le fournisseur d’emplacement fusionné) utilise à la fois le GPS et le WiFi. Le GPS met un certain temps à trouver votre position tandis que le wifi est beaucoup plus rapide. Cependant, si l'un de ces 2 services est connecté, la méthode de rappel onConnected sera appelée. Et si vous essayez d'appeler immédiatement LocationClient.getLastLocation () dans la méthode onConnected, il est généralement probable que vous obtiendrez une valeur nulle si votre service de localisation wifi est désactivé. C'est simplement parce que le GPS n'est tout simplement pas assez rapide.
Activez l'option "Emplacement réseau Wi-Fi et mobile" pour résoudre le problème vous-même localement. Vous pouvez le faire en allant dans "Paramètres> Personnel> Accès à l'emplacement> Emplacement du réseau Wi-Fi et mobile".
Toutefois, si vous souhaitez résoudre le problème pour les utilisateurs de votre application, vous devez vérifier si getLastLocation () renvoie null. Si tel est le cas, demandez à votre utilisateur d'activer le service de la même manière que google map.
Espérons que cela aide.
Je faisais face à un problème similaire.
Appelez mLocationClient.getLastLocation()
dans onConnected
ou une fois la connexion aux services Google Play établie. Si vous appelez cette méthode avant la localisation du client d'emplacement, l'emplacement retourné serait null
.
Vous pouvez vérifier si le client d'emplacement est connecté par mLocationClient.isConnected()
.
J'espère que cela t'aides.
C'est la solution qui fonctionne exactement, probablement dans des circonstances légèrement différentes. Mais je voulais ajouter quelques petites explications pour que tout le monde comprenne les concepts exacts:
1) onCreate () of Android Composant (par exemple, Activité, Fragment ou Service. Remarque: pas IntentService ), build puis connect le GoogleApiClient comme ci-dessous .
buildGoogleApiClient();
mGoogleApiClient.connect();
où, l’implémentation de buildGoogleApiClient () est,
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
Plus tard sur onDestroy (), vous pouvez déconnecter GoogleApiClient en tant que,
@Override
public void onDestroy() {
Log.i(TAG, "Service destroyed!");
mGoogleApiClient.disconnect();
super.onDestroy();
}
L’étape 1 s’assure que vous construisez et connectez le GoogleApiClient.
1) La première fois que l'instance GoogleApiClient est connectée à la méthode onConnected (). Maintenant, votre prochaine étape devrait ressembler à la méthode 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
}
Ci-dessus, vous avez appelé une méthode createLocationRequest () pour créer une demande de localisation. La méthode createLocationRequest () ressemble à celle ci-dessous.
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) Maintenant, lors du rappel onLocationChange () de l'interface LocationListener, vous obtenez un nouvel emplacement.
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Location Changed!");
Log.i(TAG, " Location: " + location); //I guarantee,I get the changed location here
}
Vous obtenez ce résultat dans Logcat: 03-22 18: 34: 17.336 817-817/com.LiveEarthquakesAlerts I/LocationTracker: Emplacement: Emplacement [fusionné 37.421998, -122.084000 acc = 20 et = + 15m35s840ms alt = 0.0]
Pour pouvoir effectuer ces trois étapes, vous devez avoir configuré votre build.gradle comme suit:
compile 'com.google.Android.gms:play-services-location:10.2.1'
Vous devez vérifier si l'utilisateur a activé la localisation via Wi-Fi/GSM ou GPS. S'il n'y a pas de fournisseur de localisation disponible, vous obtenez null
.
Ce code affiche l'écran avec les paramètres de localisation:
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
J'ai rencontré des problèmes similaires lors de mes tests avec les téléphones Samsung (Android hautement personnalisé et aucun support développeur).
LocationManager et LocationClient ne reçoivent pas le GPS des fournisseurs. Ils doivent être démarrés à chaque fois que vous avez besoin de leur emplacement. Faites cela avant votre LocationManager.getLastKnownLocation
OR LocationClient.getLastLocation
appels. Ces API vont revenir.
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) {
}
});
Vous devrez également demander explicitement l'autorisation d'emplacement pendant l'exécution , conformément à https://developer.Android.com/training/permissions /requesting.html ainsi que de l'avoir dans le fichier manifeste.
Aucune erreur explicite ne se produira si vous ne disposez pas des autorisations au moment de l'exécution, le fournisseur d'emplacement renverra simplement la valeur null.
Cela aiderait Google à documenter cela et à lancer une exception plutôt que de renvoyer null. Retourner null est à peu près la chose la moins utile à faire dans cette situation.
J'étais également confronté au même problème sur mon application, et la seule chose qui manquait était que l'application ne demandait que ACCESS_COARSE_LOCATION et non ACCESS_FINE_LOCATION. J'ai ajouté la permission plus tard et tout a bien fonctionné.
La géolocalisation des services de Google Play ne peut fonctionner sans connexion Internet, indifféremment pour le GPS. Alors, s'il vous plaît vérifier l'application avec les données mobiles activées.
Vous avez juste besoin d'une demande de mise à jour pour l'emplacement. Si avec 26 Android les autorisations du SDK sont tout à fait correctes:
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;
}
}
});
}
et dans la méthode de rappel 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();
}