web-dev-qa-db-fra.com

LocationListener de NETWORK_PROVIDER est activé mais, onLocationChanged n'est jamais appelé

Je développe une application qui obtient la position du téléphone portable toute la journée en 6 et 6 minutes dans un service, cela fonctionne très bien mais parfois la méthode OnLocationChanged de l'auditeur du fournisseur de réseau cesse d'être appelée, et je ne sais pas pourquoi.

Pour une raison quelconque, il cesse d'être appelé, mais le fournisseur est activé et la liste fonctionne, lorsque j'active ou désactive manuellement le fournisseur, onProviderEnabled et onProviderDisabled est appelé.

Cela arrive juste avec NETWORK_PROVIDER, le GPS_PROVIDER fonctionne bien.

Auditeur:

LocationListener locationListenerGPS = new LocationListener() {
        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerGPS onStatusChanged
            Log.d(TAG, "Provedor trocado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        // @Override
        public void onLocationChanged(Location location) {

            longitudeGPS = location.getLongitude();
            latitudeGPS = location.getLatitude();
            Log.d(TAG,"LocationChangedGPS LAT: "+latitudeGPS+" longi: "+longitudeGPS);
            gpsComSinal = true;
        }
    };

    LocationListener locationListenerNET = new LocationListener() {

        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerNET onStatusChanged
            Log.d("Contele", "Provedor foi mudado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        @Override
        public void onLocationChanged(Location location) {
            longitudeNET = location.getLongitude();
            latitudeNET = location.getLatitude();
            Log.d(TAG,"LocationChangedNET LAT: "+latitudeNET+" longi: "+longitudeNET);
            netComSinal = true;
        }
    };

Code:

public void initProviders() {

        localizacao = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);


        localizacao.removeUpdates(locationListenerNET);
        localizacao.removeUpdates(locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
                0, locationListenerNET);

        Log.d(TAG,"EsperaGPS");
        Handler esperaGPS = new Handler() {
            public void handleMessage(Message msg) {

                requestGPS();
            }
        };

        Message msgEsperaGPS = Message.obtain();
        msgEsperaGPS.what = 0;
        esperaGPS.sendMessageDelayed(msgEsperaGPS, 35000);
    }



    public void requestGPS() {
            if (gpsComSinal) {
                Log.d(TAG,"PEGO SINAL DE GPS");
                rastreio = "GPS";
                longitude = longitudeGPS;
                latitude = latitudeGPS;
                Log.d(TAG, "Utilizando provedor GPS.");
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);

            } else {
                Log.d(TAG,"Sem GPS... pegar NEt");
                // Setando os valores para usar network
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);
                localizacao
                        .requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                0, 0, locationListenerNET);
                Log.d(TAG,"EsperaNET");

                        requestNET();
            }
        }

    public void requestNET() {
            if (netComSinal) {
                Log.d(TAG,"PEGO SINAL DE NET");
                rastreio = "NET";
                longitude = longitudeNET;
                latitude = latitudeNET;
                Log.d(TAG, "Utilizando provedor NET.");
                localizacao.removeUpdates(locationListenerNET);

            } else {
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);
                Log.d(TAG,"Sem sinal");
            }
        }

Signaler dans un Samsung Galaxy S3: enter image description here

Toujours "Seminal" pendant 4 jours consécutifs.

Ce problème s'est déjà produit avec Galaxy Y et LG Optimus l5

J'ai fait un autre test pour voir si d'autres applications ont obtenu les positions NET, et j'ai découvert qu'elles passent pour le même problème, elles ne peuvent pas obtenir la position NET juste la GetLastknowLocation; pour tester que j'ai utilisé un Galaxy S3 avec ce problème, et j'ai désactivé le fournisseur GPS. (Testé à Cerberus).

Je n'ai trouvé aucune explication pour laquelle l'auditeur NETWORKSLOCATIONS cesse de donner des positions, mais c'est peut-être parce que cela ne devrait pas fonctionner pendant 2 ou 3 jours sans arrêt.

J'ai fait quelques tests avec d'autres applications pour voir si ce problème ne se produit qu'avec mon application, et j'ai découvert qu'ils passent pour le même problème, comme dans Cerberus par exemple:

Je désactive le fournisseur GPS dans un téléphone portable (Galaxy S3) avec le problème "Sem sinal", jetez un œil:

Mon rapport: enter image description here

Et le rapport Cerberus (imprimé le 14/05/2013): enter image description here

Mais quand j'ai ouvert Google Maps, cela semble fonctionner, j'ai essayé de me déplacer vers un endroit éloigné pour voir si cela allait montrer le GetLastknowLocation, mais non, google maps m'a mis au bon endroit pour le moment , j'ai donc réalisé que Google Maps utilisait motionevent pour me déplacer sur la carte;

Et imprimez également le journal de Google Maps pour obtenir NetWorkProvider:

Cas normal:

enter image description here

Cas seminal:

enter image description here

42

j'ai rencontré des problèmes similaires avec le fournisseur de réseau et la seule solution était de forcer le redémarrage du périphérique . Bien que google map montre toujours un emplacement correct, car il utilise d'autres informations de capteurs également en dehors du fournisseur de localisation réseau.

Mais voici une bonne nouvelle , pas depuis longtemps Google a introduit les API de Fused Location Provider via son Google Play Service Framework qui est super facile à utiliser que les fournisseurs de localisation GPS/réseau.

Compatible jusqu'à l'API niveau 8, maintenant quand j'obtiens ce problème étrange de fournisseur de réseau, Fused Location me donne en même temps un emplacement précis (sans redémarrage de l'appareil).

J'ai engagé un travail Projet de test FusedLocation ici , vous pouvez cloner et vous tester ..

Ci-dessous un extrait de code: -

package com.example.fusedLoctionTest.service;

import Android.app.Service;
import Android.content.Context;
import Android.content.Intent;
import Android.location.Location;
import Android.location.LocationManager;
import Android.os.Bundle;
import Android.os.Handler;
import Android.os.IBinder;
import Android.support.v4.content.LocalBroadcastManager;
import Android.util.Log;
import com.google.Android.gms.common.ConnectionResult;
import com.google.Android.gms.common.GooglePlayServicesClient;
import com.google.Android.gms.location.LocationClient;
import com.google.Android.gms.location.LocationRequest;

public class FusedLocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, com.google.Android.gms.location.LocationListener{
    private static final LocationRequest REQUEST = LocationRequest.create()
            .setInterval(0)
            .setFastestInterval(0)
            .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    public static final String LOCATION_RECEIVED = "fused.location.received";
    private Long now;

    private LocationClient mLocationClient;
    private final Object locking = new Object();
    private Runnable onFusedLocationProviderTimeout;
    private Handler handler = new Handler();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        now = Long.valueOf(System.currentTimeMillis());
        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();
        return START_STICKY;
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d("FusedLocationService", "Fused Location Provider got connected successfully");
        mLocationClient.requestLocationUpdates(REQUEST,this);
        onFusedLocationProviderTimeout = new Runnable() {
            public void run() {
                Log.d("FusedLocationService", "location Timeout");

                Location lastbestStaleLocation=getLastBestStaleLocation();
                sendLocationUsingBroadCast(lastbestStaleLocation);

                if(lastbestStaleLocation!=null)
                    Log.d("FusedLocationService", "Last best location returned ["+lastbestStaleLocation.getLatitude()+","+lastbestStaleLocation.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis())-now)+" ms");

                if(mLocationClient.isConnected())
                    mLocationClient.disconnect();
            }
        };
        handler.postDelayed(onFusedLocationProviderTimeout, 20000);//20 sec
    }

    private void sendLocationUsingBroadCast(Location location) {
        Intent locationBroadcast = new Intent(FusedLocationService.LOCATION_RECEIVED);
        locationBroadcast.putExtra("LOCATION", location);
        locationBroadcast.putExtra("TIME", Long.valueOf(System.currentTimeMillis()-now) +" ms");
        LocalBroadcastManager.getInstance(this).sendBroadcast(locationBroadcast);
        stopSelf();
    }

    @Override
    public void onDisconnected() {
        Log.d("FusedLocationService","Fused Location Provider got disconnected successfully");
        stopSelf();
    }

    @Override
    public void onLocationChanged(Location location) {
        synchronized (locking){
            Log.d("FusedLocationService", "Location received successfully ["+location.getLatitude()+","+location.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis()-now))+" ms");

            handler.removeCallbacks(onFusedLocationProviderTimeout);
            if(mLocationClient.isConnected())
                mLocationClient.removeLocationUpdates(this);

            sendLocationUsingBroadCast(location);

            if(mLocationClient.isConnected())
                mLocationClient.disconnect();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d("FusedLocationService", "Error connecting to Fused Location Provider");
    }

    public Location getLastBestStaleLocation() {
        Location bestResult = null;
        LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Location lastFusedLocation=mLocationClient.getLastLocation();
        Location gpsLocation = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        Location networkLocation = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        if (gpsLocation != null && networkLocation != null) {
            if (gpsLocation.getTime() > networkLocation.getTime())
                bestResult = gpsLocation;
        } else if (gpsLocation != null) {
            bestResult = gpsLocation;
        } else if (networkLocation != null) {
            bestResult = networkLocation;
        }

        //take Fused Location in to consideration while checking for last stale location
        if (bestResult != null && lastFusedLocation != null) {
            if (bestResult.getTime() < lastFusedLocation.getTime())
                bestResult = lastFusedLocation;
        }

        return bestResult;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
28
Akhil

J'ai exactement le même problème et la seule solution pour moi est de redémarrer l'appareil. Ce qui est intéressant, c'est qu'aucune des applications ne dispose d'informations de localisation à l'exception de Google maps.
L'application Google Maps trouve en quelque sorte un emplacement! ..

P.S. en utilisant un LocationListener en service, donc ce n'est certainement pas un problème de mauvaise référence, d'objet mort et ainsi de suite.

4
m190

J'ai encore ce problème. Mais je cherche toujours une réponse, j'ai essayé de l'implémenter dans l'écouteur du NETWORK_PROVIDER:

public void onStatusChanged(final String provider, final int status, final Bundle extras) {
    switch( status ) {
    case LocationProvider.AVAILABLE:
                // ...
        break;
    case LocationProvider.OUT_OF_SERVICE:
                // ...
        break;
    case LocationProvider.TEMPORARILY_UNAVAILABLE:
                // ...
        break;
    }
}

Parce que: OUT_OF_SERVICE si le fournisseur est hors service, et cela ne devrait pas changer dans un avenir proche; TEMPORARILY_UNAVAILABLE si le fournisseur est temporairement indisponible mais devrait être disponible sous peu; et DISPONIBLE si le fournisseur est actuellement disponible. onStatusChanged

Et je pensais que le OUT_OF_SERVICE était mon problème, et il n'y a pas de solution à ce jour, juste en redémarrant l'appareil, puis j'ai essayé de faire quelques rapports lorsque cela se produit et lorsque cet ocurre je demande à l'utilisateur de re-rebot l'appareil, mais peu d'appareils reçoivent ce statut.

4

Semble un bogue ouvert, problème de fournisseur de réseau signalé à Android Open Source Project, Issue Tracker: https://code.google.com/p/Android/issues/detail?id = 57707 . En bref: problème signalé le 17 juillet 2013 - dernier blog le 7 janvier 2015, le problème est apparu à partir de Android 4.1.x, apparaît dans une grande variété d'appareils, "Non résolu dans la dernière bibliothèque du service Play ", aucune solution de contournement suggérée dans le blog.

3
user5833054

Je comprends quelque chose dans notre question; vous appelez la méthode requestGPS puis découvrez son emplacement. Si le gps est activé, obtenu via le gps. Othervise gott via NET. Lorsque vous appelez requestGPS et le fournisseur de contrôle, obtenez lat-lang mais supprimez les mises à jour (n'appelez pas car vous avez supprimé le déclencheur des mises à jour);

if (gpsComSinal) {
    Log.d(TAG,"PEGO SINAL DE GPS");
    rastreio = "GPS";
    longitude = longitudeGPS;
    latitude = latitudeGPS;

    Log.d(TAG, "Utilizando provedor GPS.");
    // if you remove update don't call onLocationChanged
    localizacao.removeUpdates(locationListenerGPS); 
    localizacao.removeUpdates(locationListenerNET);
} else {
    Log.d(TAG,"Sem GPS... pegar NEt");
    // Setando os valores para usar network
    localizacao.removeUpdates(locationListenerGPS);
    localizacao.removeUpdates(locationListenerNET);
    localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                       0, 0, locationListenerNET);
    Log.d(TAG,"EsperaNET");
    requestNET();
}
2
nurisezgin

NETWORK_PROVIDER ne se met pas à jour lorsque le GPS du téléphone fonctionne et reçoit un signal. Si vous désactivez le GPS et forcez le téléphone à obtenir sa position sur le réseau, vous recommencerez à recevoir les mises à jour.

2
John

Je pense que c'est parce que votre application est "tuée" en arrière-plan. J'ai déjà rencontré ce problème et je l'ai résolu en déplaçant la création de LocationListener dans un service. Veillez également à conserver une référence à l'auditeur. Cela pourrait peut-être résoudre le problème.

1
Toverbal