web-dev-qa-db-fra.com

LocationClient getLastLocation () return null

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.

57
oscarthecat

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.

51
David

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é.

Solution

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).

21
Saran

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.

19
Tim Hong

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.

7
Rahul Sainani

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'
5
Uddhav Gautam

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));
5
Pitel

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) {
        }
    });
4
Siddharth

Sur les versions du SDK 23

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.

3
Mark

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é.

2
gfhuertac

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.

0
user1575120

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();
    }
0
CodeToLife