OnLocationChanged callback никогда не вызывается
Я пытаюсь получить текущее местоположение пользователей с помощью LocationManager
. Я провел много исследований и не могу найти никого с той же проблемой. Обратный вызов OnLocationChanged
никогда не вызван. Ниже приведен мой код и логарифм.
protected LocationListener locationListener;
protected LocationManager locationManager;
protected Context context;
Мой OnCreate()
метод
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "IN ON CREATE");
this.context = getActivity();
registerLocationUpdates();
}
Мой registerLocationUpdates
метод
void registerLocationUpdates() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_LOW);
criteria.setPowerRequirement(Criteria.POWER_LOW);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
locationManager = (LocationManager)getActivity().getSystemService(LOCATION_SERVICE);
provider = locationManager.getBestProvider(criteria, true);
// Cant get a hold of provider
if (provider == null) {
Log.v(TAG, "Provider is null");
showNoProvider();
return;
} else {
Log.v(TAG, "Provider: " + provider);
}
locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(provider, 1L, 1f, locationListener);
// connect to the GPS location service
Location oldLocation = locationManager.getLastKnownLocation(provider);
if (oldLocation != null) {
Log.v(TAG, "Got Old location");
latitude = Double.toString(oldLocation.getLatitude());
longitude = Double.toString(oldLocation.getLongitude());
waitingForLocationUpdate = false;
getNearbyStores();
} else {
Log.v(TAG, "NO Last Location found");
}
}
Мой LocationListener
private class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
latitude = Double.toString(location.getLatitude());
longitude = Double.toString(location.getLongitude());
Log.v(TAG, "IN ON LOCATION CHANGE");
if (waitingForLocationUpdate) {
getNearbyStores();
waitingForLocationUpdate = false;
}
locationManager.removeUpdates(this);
}
public void onStatusChanged(String s, int i, Bundle bundle) {
Log.v(TAG, "Status changed: " + s);
}
public void onProviderEnabled(String s) {
Log.e(TAG, "PROVIDER DISABLED: " + s);
}
public void onProviderDisabled(String s) {
Log.e(TAG, "PROVIDER DISABLED: " + s);
}
}
Мои разрешения в AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
И, наконец, logcat после запуска моего приложения
01-25 09:43:10.963: VERBOSE/NearbyListFragment(3060): IN ON CREATE
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.973: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): Provider: gps
01-25 09:43:10.983: DEBUG/LocationManager(3060): requestLocationUpdates: provider = gps, listener = co.fusionweb.[email protected]46ef4680
01-25 09:43:10.983: DEBUG/GpsLocationProvider(1329): setMinTime 1
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): NO Last Location found
01-25 09:43:10.983: VERBOSE/LocationManagerService(1329): _requestLocationUpdates: listener = Receiver{47421e68 Listener [email protected]}
01-25 09:43:11.003: VERBOSE/countingFragment(3060): IN ON CREATE VIEW
01-25 09:43:11.003: WARN/GpsLocationProvider(1329): Duplicate add listener for co.fusionweb.dealsplus
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): In Constructor
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): Scrolling
01-25 09:43:11.033: DEBUG/GpsLocationProvider(1329): startNavigating
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_time_out(standalone = 60, agps = 89)
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_accuracy(accuracy = 50)
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): persist.radio.agps.mode: []
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_position mode, client = 1, interval = 1, mode = 1
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl called: client = 1, ioctl_type = 2
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_ioctl
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [96]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_api_sync_ioctl: select_id = 0, loc_ioctl returned 0
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): Callback received: 80 (cb_id=0x5310000 handle=1)
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl result: client = 1, ioctl_type = 2, SUCCESS
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_start
01-25 09:43:11.043: DEBUG/locapi_rpc_glue(1329): loc_start_fix
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [44]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.053: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.113: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.113: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_SESSION_BEGIN
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.113: VERBOSE/GpsLocationProvider(1329): reportStatus status: 1
01-25 09:43:11.113: DEBUG/GpsLocationProvider(1329): Acquiring wakelock
01-25 09:43:11.123: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.183: DEBUG/PowerManagerService(1329): New lightsensor value:40, lcdValue:77
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.273: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.273: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_ENGINE_ON
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.273: VERBOSE/GpsLocationProvider(1329): reportStatus status: 3
И части локации Android SDK логарифма продолжают повторяться. Я пробовал все, о чем я мог думать и видел в google и stackoverflow. Als, как побочная заметка, я смог заставить ее работать на устройстве 2.3, используя requestSingleUpdate
, который доступен в API 9, и следуя руководству Deep Dive into Location, но мне нужно, чтобы он работал на 2.1 или 2.2 и выше, используя старый SDK. Если у вас есть какие-либо намеки или вы хотите узнать больше, сообщите мне. Спасибо заранее.
Ответы
Ответ 1
Похоже, что вы должны работать, потому что это не так, я бы сделал ваш пример максимально простым для устранения неполадок. Я бы сделал ваш запрос похожим на
requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
Таким образом вы получите ВСЕ обновления. И прокомментируйте часть о том, как получить последнее известное место. Это еще не нужно.
Тогда в onLocationChanged()
просто
Log.v(TAG, "IN ON LOCATION CHANGE, lat=" + latitude + ", lon=" + longitude);
Прокомментируйте остальное, чтобы вы продолжали активным слушателем. Это должно дать вам поток обновлений на реальном устройстве. На эмуляторе вам нужно будет использовать DDMS, и каждый раз, когда вы нажимаете send, вы получите одно обновление GPS.
Ответ 2
Замена
LocationManager.GPS_PROVIDER
с
LocationManager.NETWORK_PROVIDER
решил мою проблему.
Вот фрагмент кода моего менеджера местоположений
LocationManager locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);
//Проверяем разрешения на размещение, Marshmallow и выше
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
Toast.makeText(getActivity(), "Not Enough Permission", Toast.LENGTH_SHORT).show();
return;
}
//Получить текущее местоположение для начала с
Location myLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
currentLatitude = myLocation.getLatitude();
currentLongitude = myLocation.getLongitude();
//Обновление местоположения запроса с помощью LocationManager.NETWORK_PROVIDER
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, MapFragment.this);
Ответ 3
Поставщик GPS отключит, когда устройство находится в режиме пониженного энергопотребления или использует режим энергосбережения, тогда в этом случае мы не сможем получить onLocationChanged
Поставщик GPS вряд ли когда-либо вернет местоположение, если вы остаетесь в доме или здании (только хорошо работают на улице)
Поэтому в своем приложении я буду использовать GPS_PROVIDER
и NETWORK_PROVIDER
, чтобы лучше получать onLocationChanged()
https://developer.android.com/guide/topics/location/strategies.html#Updates
Чтобы запросить обновления местоположения у поставщика GPS, используйте GPS_PROVIDER вместо NETWORK_PROVIDER. Вы также можете запросить обновления местоположения как от GPS, так и от провайдера сетевых расположений, позвонив requestLocationUpdates() дважды - один раз для NETWORK_PROVIDER и один раз для GPS_PROVIDER.
Ответ 4
Как писал Стив Блэквелл, ваша установка хороша. Что вы можете попробовать, так это понять, если у вас 100% фиксированный сигнал GPS! Я установил хорошее приложение GPS Tester (из магазина воспроизведения), и оно покажет вам, есть ли у вас исправление или нет, и к каким спутникам вы и что является прочностью соединения.
Именно по этой причине мой OnLocationChanged() никогда не звонил.. Я попытался запустить его изнутри здания:\
Удачи!
Ответ 5
У меня возникла аналогичная проблема. У меня были разрешения, исправленные запросы, но обновления не было. Оказалось, что все, что я должен был сделать, это просто подождать. Пока я искал проблему в Интернете, у меня было приложение, и через несколько минут оно только начинало получать обновления. Тогда даже когда я убил приложение и запустил его снова, обновления пришли мгновенно - я думаю, это системная вещь, некоторые оптимизации, возможно, из-за того, что устройство вообще не двигалось (кстати, это не какое-то дерьмовое устройство, это Pixel).
Ответ 6
У меня была такая же ситуация, я думал, что допустил ошибку в своем коде, поэтому метод onlocationchage не вызван, наконец, я разрешил это.
Step 1 :
Close your application and Open Google Map Application.
Step 2 :
Touch the location finder button or icon over the Google Map app then It will show, currently where you are located.
Step 3 :
Now Run your app and check onlocationchage will call.
Ответ 7
Извините, что натолкнулся на такую старую ветку, но это может пригодиться некоторым другим, так как этот вопрос занимает относительно высокое место в поиске Google.
У меня была похожая проблема, onlocationchanged не запускалось, но я не смог найти ничего плохого в своем коде. Попробовав все виды комбинаций, я понял, что основной причиной проблемы был тот факт, что я регистрировал слушателя в сервисе.
Служба была приоритетной службой, поэтому, основываясь на документации Google, которая должна работать, она НЕ СДЕЛАЛА!
Обертывание инициализации в методе и вызов метода из действия, которое создало или связало со службой, решило мою проблему.
Это мой метод в моем сервисе:
void start_gps_track(int i) {
if (myCarLocationListener!=null) {
if (i==1) //if start night
myCarLocationListener.setNightstart(true);
else if (i==2) //if start GPS
myCarLocationListener.setLocationStart(true);
return;
}
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if ( locationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
myCarLocationListener=new CarLocationListener(this,adjust_audio);
if (i==1) //if start night
myCarLocationListener.setNightstart(true);
else if (i==2) //if start GPS
myCarLocationListener.setLocationStart(true);
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, myCarLocationListener);
Log.d("HU","Registered location listener");
Location lastlocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (lastlocation == null)
lastlocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastlocation != null)
myCarLocationListener.onLocationChanged(lastlocation);
}
catch (SecurityException e){
Log.e("HU-GPS","No permission to access Location");
}
}
else
{
Log.e("HU-GPS","No GPS provider or no permission");
}
}
Если я вызову это из самой Службы, я не получу никаких обновлений местоположения (опять же, обратите внимание, что служба FOREGROUND является службой, и она фактически привязана к действию, которое в данный момент выполняется).
Однако, если я вызываю этот метод из действия, которое создало/привязало к сервису, как показано ниже, он работает нормально:
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
TransporterService.LocalBinder binder = (TransporterService.LocalBinder) service;
mService = binder.getService();
mService.updatePlayer(player.this);
try {
mService.start_gps_track(0);
}
catch (Exception e) { //This should only happen if there is no GPS provider available, but it might happen quickly after boot when the device is not yet ready.
mService.recheck_gps(0);
}
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
Надеюсь, что это поможет некоторым другим, кто сталкивается с этой проблемой.
Ответ 8
Я столкнулся с такой же проблемой. Я получил getLastKnownLocation как null. Проблема разрешается, когда я перезапускал как устройство, так и службу местоположения на устройстве.
Ответ 9
Если вы пытаетесь использовать NETWORK_PROVIDER, это действительно сложно проверить:
- на эмуляторе: никогда не работайте
- на реальном устройстве: только getLastKnownLocation() работает, чтобы получать onLocationChanged(), вы должны использовать мобильные данные и выйти на улицу с риском потери телефона от грабителя: P
Я предполагаю, что причина в том, что это просто местоположение сетевого провайдера, а не только ваше устройство, а сетевой провайдер никогда не перемещается, поэтому onLocationChanged() никогда не звонит. Это может произойти только при переключении между мобильными данными и Wi-Fi и наоборот. Пожалуйста, поправьте меня, если я ошибаюсь.
Поэтому я предлагаю использовать GPS_PROVIDER для экспериментов перед рассмотрением производительности и использования батареи. Он отлично работает как на эмуляторах, так и на реальных устройствах. Для лучшей практики: https://developer.android.com/guide/topics/location/strategies.html
Мне потребовалось несколько часов для тестирования с NETWORK_PROVIDER без каких-либо результатов, поэтому, надеюсь, мое предложение будет полезно.
Ответ 10
У меня была та же проблема (onLocationChanged() никогда не вызывался с NETWORK_PROVIDER) на моем реальном устройстве (M, app targetSDK 23), пока я не перезапустил его.
Ответ 11
Как ответил Phan Van Linh
, это возможно потому, что вы внутри здания. Есть объяснение здесь о том, как издеваются GPS для эмулятора. Кроме того, есть это приложение, которое высмеивает данные GPS.
Ответ 12
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (manager != null) {
List<String> providers = manager.getAllProviders();
for (String provider : providers) {
manager.requestLocationUpdates(provider, TIME_BW_UP, DISTANCE_BW_UP, locationListener);
}
}
Ответ 13
У меня 2 устройства: Samsung Galaxy S4 (Android 5.0.1) и Vertex Win (Android 8.1).
На Samsung все работает правильно и быстро, GPS-координаты найдены, и вызывается onLocationChanged
.
На Vertex in prioity PRIORITY_BALANCED_POWER_ACCURACY
он, вероятно, сначала взаимодействует с провайдером сети, поэтому он находит координаты через Wi-Fi. Но он не может правильно определить, включена ли служба определения местоположения (через некоторое время устройство думает, что оно включено, когда оно выключено, и вызывает метод addOnSuccessListener
LocationServices.getSettingsClient
. Поэтому я переключился на PRIORITY_HIGH_ACCURACY
и Еще один сюрприз. Сетевой провайдер отключен, но onLocationChanged
не вызывался, поэтому я не мог получить координаты. Я скачал GPS tester
(как советовал @Li3ro) с Play Market и увидел, что спутники видны, но без исправления сигнал. Я не смог получить сигнал внутри здания.
Даже автономные карты не могли получить координаты, но на улице могли. Поэтому, после того как я ушел, я смог найти свои координаты в приложении.
См. также fooobar.com/questions/409619/..., где говорится о приоритетах и распознавании ошибок (отключение GPS через некоторое время, если координаты не найдены).
Ответ 14
Это должно произойти из-за настроек вашего телефона. В настройках местоположения телефонов, если в качестве режима службы определения местоположения задано только GPS, OnLocationChanged обратный вызов вызывает, когда есть GPS Fix. Выбрав опции "Использовать GPS, WI-FI и мобильные сети", местоположение будет определяться с помощью этих трех провайдеров. Это займет меньше времени, чтобы определить местоположение вашего устройства.
*** Путь к доступу к службам определения местоположения может быть изменен с устройства на устройство.
Спасибо