android - permission - LocationListener de NETWORK_PROVIDER está habilitado pero nunca se llama a onLocationChanged
google api client location android (7)
Creo que es porque tu aplicación se ''mata'' en el fondo. Me he enfrentado a este problema antes y lo resolví moviendo la creación del LocationListener en un servicio. Asegúrese de mantener una referencia al oyente también. Simplemente podría resolver el problema.
Estoy desarrollando una aplicación que obtiene la posición del teléfono celular todo el día en 6 y 6 minutos en un servicio, funciona bien, pero a veces el método OnLocationChanged
del oyente del proveedor de la red deja de llamarse, y no sé por qué.
Por alguna razón, deja de llamar, pero el proveedor está habilitado y el Lister está funcionando, cuando onProviderEnabled
o deshabilito el proveedor manualmente, se llama a onProviderEnabled
y onProviderDisabled
.
Simplemente sucede con NETWORK_PROVIDER
, el GPS_PROVIDER
funciona bien.
Oyente:
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;
}
};
Código:
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");
}
}
Informe en un Samsung Galaxy S3:
Todavía recibes "Sem sinal" por 4 días seguidos.
Este problema ya ha sucedido con Galaxy Y y LG Optimus l5
He realizado otra prueba para ver si otras aplicaciones obtuvieron las posiciones NET, y descubrí que están pasando por el mismo problema, no pueden obtener la posición NET solo GetLastknowLocation; para probar que utilicé un Galaxy S3 con este problema, y desactivé el proveedor de GPS. (Probado en Cerberus).
No pude encontrar ninguna explicación de por qué NETWORKSLOCATIONS oyente deja de dar posiciones, pero podría ser porque no debería funcionar durante 2 o 3 días sin parar.
He hecho algunas pruebas con otras aplicaciones para ver si este problema acaba de ocurrir con mi aplicación, y descubrí que están pasando por el mismo problema, como en Cerberus, por ejemplo:
Desactivo el proveedor de GPS en un teléfono celular (Galaxy S3) con el problema "Sem sinal", eche un vistazo:
Mi reporte:
Y Cerberus (impresión tomada el 14/05/2013) informa:
Pero cuando abrí Google Maps, parece que funciona bien, traté de moverme a un lugar distante para ver si mostraba GetLastknowLocation
, pero no, los mapas de google me pusieron en el lugar correcto en el momento, así que me di cuenta de que Google Maps usaba motionevent para moverme al mapa;
Y también imprima el Registro de Google Maps para obtener NetWorkProvider:
Caso normal:
Caso seminal:
NETWORK_PROVIDER no se actualiza cuando el GPS del teléfono se está ejecutando y recibe una señal. Si apaga el GPS y fuerza al teléfono a obtener su ubicación de la red, comenzará a recibir actualizaciones nuevamente.
Parece un error abierto, problema de proveedor de red informado en Android Open Source Project, Issue Tracker: https://code.google.com/p/android/issues/detail?id=57707 . En resumen: problema informado el 17 de julio de 2013: el último blog del 7 de enero de 2015 apareció en Android 4.1.x, aparece en una amplia variedad de dispositivos, "No se resolvió en la última biblioteca de servicio Play", no se sugirieron soluciones alternativas en el blog.
Tengo exactamente el mismo problema y la única solución para mí es reiniciar el dispositivo. Lo interesante es que ninguna de las aplicaciones tiene información de ubicación, excepto mapas de Google.
¡La aplicación Google Maps encuentra de alguna manera una ubicación!
PD usando un LocationListener en servicio, por lo que definitivamente no es un problema de mala referencia, objeto muerto, etc.
Todavía tengo este problema. Pero todavía estoy buscando una respuesta, traté de implementar esto en el oyente de 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;
}
}
Porque: OUT_OF_SERVICE si el proveedor está fuera de servicio, y no se espera que esto cambie en el futuro cercano; TEMPORARILARMENTE NO DISPONIBLE si el proveedor no está disponible temporalmente, pero se espera que esté disponible en breve; y DISPONIBLE si el proveedor está disponible actualmente. onStatusChanged
Y pensé que OUT_OF_SERVICE era mi problema, y no hay solución hasta el momento, simplemente reiniciando el dispositivo, luego traté de hacer algunos informes cuando esto sucede y cuando esto ocurre le pido al usuario que reembarque el dispositivo, pero pocos dispositivos lo reciben este estado.
Yo entiendo algo en nuestra pregunta; llama al método requestGPS y luego descubre su ubicación. Si gps está habilitado, se obtiene a través de gps. Othervise gott vía NET. Cuando llame a requestGPS y al proveedor de control, obtenga el lat-lang pero elimine las actualizaciones. (No llame porque eliminó el activador de actualizaciones);
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();
}
he tenido problemas similares con el proveedor de red y solo se reinició la solución. Aunque el mapa de Google mostraba siempre la ubicación correcta, porque usa otros sensores de información además del proveedor de ubicación de red.
Pero esta es una buena noticia , no Hace mucho tiempo Google introdujo la API de Proveedor de ubicación fusionada a través de su Marco de servicios de Google Play, que es muy fácil de usar que los proveedores de localización por GPS / red.
Compatible hasta API nivel 8, ahora cuando recibo este extraño problema de proveedor de red, mismo tiempo Ubicación fusionada me da una ubicación precisa (sin reinicio del dispositivo).
Aquí he contratado un proyecto de prueba de FusedLocation en funcionamiento . Puede clonarse y probarse.
Debajo hay un fragmento de código: -
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;
}
}