android verificare Il fornitore di localizzazione fuso non sembra utilizzare il ricevitore GPS




smartphone con migliore ricezione gps (10)

Dal momento che nessuno ha condiviso questo link, ho trovato che questa è la documentazione più utile http://developer.android.com/guide/topics/location/strategies.html

"È probabile che la correzione della posizione più recente sia la più accurata, tuttavia, poiché la precisione di una correzione della posizione varia, la correzione più recente non è sempre la migliore. È necessario includere la logica per la scelta delle correzioni della posizione in base a diversi criteri. i criteri variano anche in base ai casi d'uso dell'applicazione e ai test sul campo. "

La soluzione migliore è mantenere un ascoltatore di posizione attivo finché l'attività è in primo piano e selezionare la posizione cache più precisa quando si preme il pulsante. Potrebbe essere necessario mostrare uno spinner o qualcosa del genere e disabilitare il pulsante mentre attende che venga visualizzata una misurazione accurata.

Android 4.3 su Moto G, Android 4.4.2 su Nexus 7 2012, Android 4.4.2 su Nexus 5. Android Studio 0.4.

Non desidero ricevere aggiornamenti regolari sulla posizione, voglio solo una posizione precisa quando l'utente preme un pulsante.

Ho seguito questo esempio: https://developer.android.com/training/location/retrieve-current.html

Nel file manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Controllo che i Servizi di gioco siano disponibili utilizzando GooglePlayServicesUtil.isGooglePlayServicesDisponibili

Nell'attività principale:

//in activity onCreate method
mLocationClient = new LocationClient(this, this, this);

@Override
protected void onStart() {
    mLocationClient.connect();
    super.onStart();
}

@Override
protected void onStop() {
    mLocationClient.disconnect();
    super.onStop();
}

//in button onclick method    
mCurrentLocation = mLocationClient.getLastLocation();

Non ho carta SIM. Se abilito il Wifi, a volte ottengo una posizione precisa. Altre volte mCurrentLocation è null.

Se disattivo Wifi, mCurrentLocation è sempre nullo.

Sto testando fuori in diverse posizioni sempre con una chiara visione del cielo. Ho aspettato tre minuti in ogni luogo.

Non vedo mai l'icona GPS visualizzata sulla barra delle notifiche di Android nella parte superiore dello schermo.

Ho queste impostazioni di posizione:

Un'app GPS Test riesce a utilizzare il GPS con successo all'interno dello stesso dispositivo con Wi-Fi disabilitato in modo che il GPS funzioni:

Anche la registrazione per gli aggiornamenti di posizione, come in https://developer.android.com/training/location/receive-location-updates.html , non funziona. Metodo registrato mai chiamato.

Che cosa sto facendo di sbagliato?


Secondo i documenti

Questo metodo fornisce un modo semplificato per ottenere la posizione. È particolarmente adatto per applicazioni che non richiedono una posizione precisa e che non desiderano mantenere una logica aggiuntiva per gli aggiornamenti di posizione.

quindi può o non può restituire una posizione altamente precisa.

Il GPS può richiedere un po 'di tempo per bloccarsi, quindi chiamare getLastLocation può o meno restituire una posizione

è meglio richiedere gli aggiornamenti di posizione, quindi dopo aver ottenuto una posizione basta interrompere la richiesta di aggiornamenti di posizione.

Anche guardando il codice che hai fornito stai aspettando che il LocationClient connetta prima di provare a ottenere una posizione? Questo ti darà sicuramente una posizione nullo poiché non è ancora connesso per ottenere la posizione.

quello che dovresti fare è nel tuo onConnected ottenere l'ultima posizione lì, ad esempio

public void onConnected(Bundle connectionHint) {
    Location location = mLocationClient.getLastLocation();
}

come si dice in quell'esempio onConnected è Called by Location Services when the request to connect the client finishes successfully. At this point, you can request the current location or start periodic updates Called by Location Services when the request to connect the client finishes successfully. At this point, you can request the current location or start periodic updates


Senza una carta SIM, il coarse location provider non ha modo di conoscere la posizione approssimativa, a meno che non sia in grado di trovare una rete WiFi mappata da Google.

Richiedere l'ultima posizione nota può comportare una posizione obsoleta e, in quanto tale, è piuttosto inutile. Immagino che questa sia la posizione che è stata registrata l'ultima volta che alcune app hanno richiesto un aggiornamento della posizione.

Io uso il seguente codice per ottenere una posizione recente:

    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_COARSE);
    criteria.setAltitudeRequired(false);
    criteria.setSpeedRequired(false);
    criteria.setBearingRequired(false);
    criteria.setCostAllowed(false);

    final LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    ....
    LocationListener listener = new LocationListener() {
        @Override
        public void onLocationChanged(Location lastKnownLocation) {
                     ....
        }
        // rest of interface
     }


     manager.requestSingleUpdate(criteria, listener, null);

L'ultima chiamata garantisce che chiediamo la posizione corrente , non la posizione in cui è stata in grado di trovare una quantità sconosciuta di tempo prima.

Potresti provare a cambiarlo in Criteria.ACCURACY_FINE per attivare il GPS. Essere consapevoli del fatto che se il GPS non ha avuto una correzione per un po 'di tempo potrebbe richiedere più di alcuni minuti prima che sia effettivamente in grado di ottenere una correzione. Mi aspetterei nel frattempo che vedresti l'icona GPS che indica che è in attesa di una correzione.


Tutto quello che devi fare è aggiungere una proprietà prioritaria all'oggetto richiesta come questo.

public void onConnected(Bundle arg0)
{
    locationrequest = LocationRequest.create();
    locationrequest.setInterval(1000);
    locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationclient.requestLocationUpdates(locationrequest, this);
}

Forse utilizzare una variabile booleana per consentire all'utente di avere opzioni per forzare il GPS

boolean forceGPS=false;
.
.
.//make the user choose to change the value of the boolean
.
.
public void onConnected(Bundle arg0)
    {
        locationrequest = LocationRequest.create();
        locationrequest.setInterval(1000);
        if(forceGPS==true)
        {
        locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
        locationclient.requestLocationUpdates(locationrequest, this);
    }

Cosa c'è nel metodo OnConnected ?

In questo metodo devi creare l'oggetto LocationRequest con priorità PRIORITY_HIGH_ACCURACY .

@Override
public void onConnected(Bundle dataBundle) {
    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationClient.requestLocationUpdates(mLocationRequest, fusedListener);
}

Preferisco utilizzare il servizio che implementa LocationListener per ottenere l'attuale posizione quasi accurata. Di solito faccio i seguenti passaggi:

  1. Inizializza LocationManager e chiama requestLocationUpdates per GPS_PROVIDER e NETWORK_PROVIDER in onCreate()
  2. Chiama getLastKnownLocation per GPS_PROVIDER e NETWORK_PROVIDER e utilizza getTime() per conoscere l'ultima posizione più recente.
  3. Trasmetti l'ultima posizione (se è <30 sec vecchio) (opzionale)
  4. Nel frattempo, quando viene chiamato onLocationChanged confronto la posizione appena aggiornata con l'ultima posizione migliore (se presente) e controllo il livello di precisione.
  5. Se il delta di precisione <MIN_ACCURACY (variabile utente), utilizzarlo come posizione migliore
  6. Trasmetti la migliore posizione corrente
  7. È necessario rimuovere LocationManager locationManager.removeUpdates(this);
  8. Chiama stopSelf (); (puoi anche interrompere il servizio dall'attività onDestroy )

MODIFICARE:

OK ... Il metodo di cui sopra utilizzava API di localizzazione, di seguito ho codificato utilizzando Fused Provider (GooglePlayServices). Ho provato il mio Nexus 5 (Android 4.4.2), NESSUN SIM, NO WIFI ... e sto ottenendo risultati.

Modifica 2: Ho anche provato su Android 2.3.3 LG Optimus (No SIM e Wifi) e ci sono voluti circa 5 minuti per ottenere il blocco (utilizzando Fused fornito), ma stavo ottenendo l'icona della posizione all'istante.

public class HomeActivity extends FragmentActivity implements
        ActionBar.OnNavigationListener,
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {

    private LocationClient locationClient;
    private LocationRequest locationRequest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_home);
            // ...
            int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resp == ConnectionResult.SUCCESS) {
            locationClient = new LocationClient(this, this, this);
            locationClient.connect();
        } else {
            Toast.makeText(this, "Google Play Service Error " + resp,
                    Toast.LENGTH_LONG).show();

        }
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        if (locationClient != null && locationClient.isConnected()) {

            locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(100);
            locationClient.requestLocationUpdates(locationRequest, this);

        }
    }

    @Override
    public void onLocationChanged(Location location) {

        try {
            if (location != null) {
                LatLng gps = new LatLng(location.getLatitude(), location.getLongitude());
                Log.v("JD", "My Location: " + gps.toString());
            }
        } catch (Exception e) {
            Log.d("JD",
                    "onLocationChanged", e);

        }       
    }
}

Penso che tu stia testando la tua applicazione in Indoor, non funziona ..

e il flusso di codice ..

public void setUpLocationClientIfNeeded() {
        createLocReq();
        if (mLocationClient == null) {
            mLocationClient = new LocationClient(getApplicationContext(), this, // ConnectionCallbacks
                    this); // OnConnectionFailedListener
        }
    }

    private void createLocReq() {
        if (mLocationRequest == null) {
            // Create a new global location parameters object
            mLocationRequest = LocationRequest.create();
            // Set the update interval
            mLocationRequest.setInterval(LocationServices.UPDATE_INTERVAL_IN_MILLISECONDS);
            // Use high accuracy
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            // Set the interval ceiling to one minute
            mLocationRequest.setFastestInterval(LocationServices.FAST_INTERVAL_CEILING_IN_MILLISECONDS);

            mLocationClient = new LocationClient(getApplicationContext(), this, this);
            mLocationClient.connect();
        }
    }

    public void updateLocation(Location location) {
        if (lastTrackedLat == 0.0) {
            lastTrackedLat = location.getLatitude();
        }
        if (lastTrackedLng == 0.0) {
            lastTrackedLng = location.getLongitude();
        }

        currentLat = location.getLatitude();
        currentLng = location.getLongitude();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            this.location = location;
            updateLocation(location);
        }
    }

    public Location getLocation() {
        // mLocationClient.getLastLocation();
        return location;
    }

Prova questo:

public final static int MINACCURACY = 50;

private LocationManager lm;
private LocationListener listener;

private void foundLoc(double x, double y) {
    // do something with x,y
    Log.v("DEBUG", x + "," + y);
}


public void findMe(View v) {
    lm = (LocationManager) getSystemService(LOCATION_SERVICE);
    listener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            if(location.getAccuracy() < MINACCURACY) {
                foundLoc(location.getLatitude(), location.getLongitude());
                lm.removeUpdates(listener);
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, listener);
}

MINACCURACY è in metri. In questo modo, premendo il pulsante (che chiama il metodo findMe), il GPS è abilitato, la posizione viene individuata con una precisione minima, il metodo foundLoc ottiene i dati e il listener termina (che, a sua volta, disabilita il GPS).


Ci sono due cose che stanno causando a volte di ottenere null , e talvolta ottenere una posizione.

Innanzitutto, stai creando una nuova istanza di LocationClient nel metodo onClick , che non è la stessa istanza che stai chiamando connect() su onStart() . Ciò creerà comportamenti imprevedibili laddove a volte il client avrà abbastanza tempo per connettersi prima di restituire un risultato da LocationClient.getLastLocation() , e talvolta non lo farà.

In secondo luogo, dovresti proteggere la chiamata a LocationClient.getLastLocation() con una chiamata a LocationClient.isConnected() . Dice quanto segue nei documenti LocationClient.isConnected() : https://developer.android.com/reference/com/google/android/gms/location/LocationClient.html#isConnected()

Verifica se il client è attualmente connesso al servizio, in modo che le richieste ad altri metodi abbiano esito positivo. Le applicazioni devono proteggere le azioni dei client causate dall'utente con una chiamata a questo metodo.

Poiché l'utente sta attivando il codice onClick() toccando il pulsante, è necessario chiamare questo metodo prima di provare a ottenere l'ultima posizione.

Quindi, il tuo codice dovrebbe assomigliare a questo:

LocationClient mLocationClient;
Location mCurrentLocation;

@Override
protected void onCreate() {
    ...
    mLocationClient = new LocationClient(this, this, this);
    ...
}

@Override
protected void onStart() {
    mLocationClient.connect();
    super.onStart();
}

@Override
protected void onStop() {
    mLocationClient.disconnect();
    super.onStop();
}

public void onClick(View v) {
    ...
    if (mLocationClient.isConnected()) {
        // You should get a valid location here
        mCurrentLocation = mLocationClient.getLastLocation();
    }
}

Questo dovrebbe dare al LocationClient un tempo sufficiente per connettersi e darti una posizione valida, che dovrebbe includere i dati GPS.


Il provider di localizzazione non attiva il GPS finché alcuni clienti non chiedono (sottoscrivi) una posizione di alta precisione (come descritto negli esempi forniti da altri utenti). L'app di test GPS non utilizza il provider di posizione ma utilizza il vecchio modo "diretto" di ottenere la posizione.

Inoltre, esiste un meccanismo di scadenza che rimuove le informazioni sull'ultima posizione dopo un po 'di tempo se si ritiene che sia obsoleto.

Riassumendo quanto sopra è davvero possibile che LP (Location Provider) non abbia nulla da darti.





google-play-services