LocationListener NETWORK_PROVIDER включен, но onLocationChanged никогда не вызывается
Я занимаюсь разработкой приложения, которое получает позицию мобильного телефона в течение всего дня за 6 и 6 минут в службе, оно работает нормально, но иногда метод OnLocationChanged
слушателя сетевого провайдера перестают вызывать, и я не знаю почему.
По какой-то причине он перестает вызываться, но поставщик включен, а список работает, когда я включаю или отключаю поставщика вручную, onProviderEnabled
а также onProviderDisabled
называется.
Это просто происходит с NETWORK_PROVIDER
, GPS_PROVIDER
работает хорошо.
Слушатель:
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;
}
};
Код:
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");
}
}
Отчет в Samsung Galaxy S3:
До сих пор получаю "Семинар" уже 4 дня подряд.
Эта проблема уже случилась с Galaxy Y и LG Optimus l5
Я сделал еще один тест, чтобы увидеть, получили ли другие приложения позиции NET, и я обнаружил, что они проходят ту же проблему, они не могут получить позицию NET только GetLastknowLocation; чтобы проверить, что я использовал Galaxy S3 с этой проблемой, и я отключил провайдера GPS. (Проверено в Цербере).
Я не смог найти объяснения, почему слушатель NETWORKSLOCATIONS перестает давать позиции, но это может быть потому, что он не должен работать в течение 2 или 3 дней без остановки.
Я провел несколько тестов с другими приложениями, чтобы выяснить, происходит ли эта проблема только с моим приложением, и я обнаружил, что они подходят к той же проблеме, как, например, в Цербере:
Я отключаю провайдера GPS в мобильном телефоне (Galaxy S3) с проблемой "Sem sinal", посмотрите:
Мой отчет:
И Цербер (отпечаток взят 14.05.2013) сообщает:
Но когда я открыл Google Карты, кажется, что все в порядке, я попытался переместиться на расстояние, чтобы посмотреть, покажет ли он GetLastknowLocation
, но нет, карты Google в настоящий момент ставят меня в нужное место, поэтому я понял, что Карты Google используют motionevent, чтобы переместить меня на карту;
А также распечатайте журнал Google Maps, чтобы получить NetWorkProvider:
Нормальный случай:
Полуфинал дела:
7 ответов
У меня были похожие проблемы с сетевым провайдером, и единственным решением было принудительное перезапуск устройства. Хотя карта Google всегда показывала правильное местоположение, потому что она использует информацию о других датчиках, кроме поставщика сетевых расположений.
Но вот хорошая новость: не так давно Google представил API-интерфейсы Fused Location Provider через Google Play Service Framework, который проще в использовании, чем провайдеры GPS / Network Location.
Совместимый до уровня API 8, теперь, когда я получаю эту странную проблему провайдера сети, в то же время Fused Location дает мне точное местоположение (без перезапуска устройства).
Я передал один рабочий тестовый проект FusedLocation здесь, вы можете клонировать и протестировать себя..
Ниже приведен фрагмент кода:-
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;
}
}
У меня все еще есть эта проблема. Но я все еще ищу ответ, я попытался реализовать это в слушателе 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;
}
}
Потому что: OUT_OF_SERVICE, если провайдер не работает, и это не должно измениться в ближайшем будущем; TEMPORARILY_UNAVAILABLE, если поставщик временно недоступен, но ожидается, что он будет доступен в ближайшее время; и ДОСТУПНО, если поставщик в настоящее время доступен. onStatusChanged
И я думал, что OUT_OF_SERVICE была моей проблемой, и до сих пор нет решения, просто перезагрузка устройства, затем я попытался сделать несколько отчетов, когда это происходит, и когда это происходит, я прошу пользователя перезагрузить устройство, но немногие устройства получают этот статус.
У меня точно такая же проблема, и единственное решение для меня - перезагрузить устройство. Что интересно, ни одно из приложений не имеет информации о местоположении, кроме карт Google.
Приложение Google maps как-то находит местоположение!..
PS использует LocationListener в сервисе, так что это определенно не проблема плохой ссылки, мертвого объекта и так далее.
Кажется, открытая ошибка, проблема с сетевым провайдером, о которой сообщалось в Android Open Source Project, Отслеживание проблем: https://code.google.com/p/android/issues/detail?id=57707. Вкратце: о проблеме сообщалось 17 июля 2013 г. - последний блог, 7 января 2015 г., проблема появилась в Android 4.1.x, появляется на самых разных устройствах, "не решена в последней библиотеке служб Play", обходные пути в блоге не предлагались.
NETWORK_PROVIDER не обновляется, когда GPS телефона работает и получает сигнал. Если вы отключите GPS и заставите телефон определить свое местоположение в сети, вы снова начнете получать обновления.
Я понимаю кое-что в нашем вопросе; Вы вызываете метод requestGPS, а затем диктуете его местоположение. Если gps включен, принимается через gps. В противном случае получил через NET. Когда вызываете requestGPS и управляете провайдером, чем получаете lat-lang, но удаляете обновления.(Не звоните, потому что вы удалили триггер обновлений);
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();
}
Я думаю, это потому, что ваше приложение "убито" в фоновом режиме. Я сталкивался с этой проблемой раньше, и я решил ее, перенеся создание LocationListener в сервис. Обязательно сохраните ссылку на слушателя тоже. Это может решить проблему.
Я столкнулся с этой проблемой и обнаружил, что поставщик сети не работает на некоторых устройствах Android. Когда вы отключаете GPS, потому что они не позволяют получить доступ к данным о местоположении, если GPS не включен.
Я пробовал это на многих устройствах 1. Примечание lenove k6 (снимок экрана1, снимок экрана2) 2. Снимок экрана Xiomai mi 9t1 3. Google Pixel 1 и Pixel 2
поэтому некоторым устройствам требуется включить GPS для доступа к местоположению из LocationManager.NETWORK_PROVIDER, и вы не можете получить данные о местоположении без включения GPS