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

Другие вопросы по тегам