web-dev-qa-db-ja.com

NETWORK_PROVIDERのLocationListenerは有効ですが、onLocationChangedは呼び出されません

私はサービスで6分と6分で一日中携帯電話の位置を取得するアプリケーションを開発しています、それはうまく動作しますが、時々ネットワークプロバイダーリスナーのメソッドOnLocationChangedが呼び出されないので、理由がわかりません。

何らかの理由で呼び出されるのを停止しますが、プロバイダーは有効であり、リスターは機能しています。プロバイダーを手動で有効または無効にすると、onProviderEnabledおよびonProviderDisabledが呼び出されます。

NETWORK_PROVIDERGPS_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でのレポート: enter image description here

4日間続けて「Sem sinal」を取得しています。

この問題は、Galaxy YとLG Optimus l5で既に発生しています。

他のアプリケーションがNETポジションを獲得したかどうかを確認するために別のテストを行いましたが、同じ問題に合格しており、GetLastknowLocationだけではNETポジションを取得できないことがわかりました。この問題でGalaxy S3を使用したことをテストし、GPSプロバイダーを無効にしました。 (ケルベロスでテスト済み)。

NETWORKSLOCATIONSリスナーがポジションの提供を停止する理由については説明が見つかりませんでしたが、停止せずに2日間または3日間機能しないはずである可能性があります。

私はこの問題が私のアプリケーションでちょうど起こっているかどうかを確認するために他のアプリケーションでいくつかのテストを行いました、そして、例えばケルベロスのように同じ問題に合格していることを発見しました:

「Sem sinal」問題のある携帯電話(Galaxy S3)でGPSプロバイダーを無効にします。

私の報告書: enter image description here

そしてケルベロス(2013年5月14日に撮影された)レポート: enter image description here

しかし、Googleマップを開いたときはうまくいくようです。GetLastknowLocationが表示されるかどうかを確認するために遠くの場所に移動しようとしましたが、Googleマップはその瞬間に適切な場所に配置しました、そのため、Googleマップではmotioneventを使用してマップ内を移動していることに気付きました。

また、Googleマップのログを印刷して、NetWorkProviderを取得します。

通常の場合:

enter image description here

Semの最終ケース:

enter image description here

42

私はネットワークプロバイダーで同様の問題を経験しましたが、唯一の解決策はデバイスの強制再起動。 Googleマップは常に正しい場所を表示していましたが、ネットワークロケーションプロバイダーとは別のセンサー情報も使用しているためです。

しかし、ここには良いニュースがありますが、久しぶりにGoogleが Googleを介してFused Location Provider apiを導入しましたPlay Service Framework これは、GPS /ネットワークロケーションプロバイダーよりも非常に使いやすいです。

APIレベル8までの互換性があり、ネットワークプロバイダーのこの奇妙な問題が発生すると、Fused Locationが正確な位置情報を提供します(デバイスの再起動なし)。

私は1つの作業をコミットしました FusedLocation Test Project here 、自分でクローンを作成してテストできます。

以下はコードのスニペットです:-

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;
    }
}
28
Akhil

私はまったく同じ問題を抱えており、唯一の解決策はデバイスを再起動することです。興味深いことに、Googleマップ以外のアプリには位置情報がありません。
Googleマップアプリはなんとなく場所を見つけます!..

PS ServiceでLocationListenerを使用するため、不正な参照、デッドオブジェクトなどの問題ではありません。

4
m190

私はまだこの問題を抱えています。しかし、私はまだ答えを探しています、私はこれを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は、プロバイダーが一時的に利用できないが、まもなく利用可能になると予想される場合。プロバイダが現在利用可能な場合はAVAILABLE。onStatusChanged

そして、私はOUT_OF_SERVICEが私の問題だと思っていたので、これまでのところ解決策はなく、デバイスを再起動するだけで、これが発生したときにこのレポートを作成しようとしましたこのステータス。

4

Android Open Source Project、Issue Tracker: https://code.google.com/p/Android/issues/detail?id = 57707 。要するに、2013年7月17日に報告された問題-2015年1月7日の最後のブログ、Android 4.1.x、さまざまなデバイスに表示される問題、最新のPlayサービスライブラリで解決済み」、ブログでは回避策は提案されていません。

3
user5833054

私たちの質問でいくつかのことを理解しています。 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();
}
2
nurisezgin

NETWORK_PROVIDERは、電話のGPSが実行中で信号を受信して​​いるときは更新されません。 GPSをオフにし、電話でネットワークから現在地を取得するように強制すると、再びアップデートの取得が開始されます。

2
John

これは、アプリがバックグラウンドで「殺される」からだと思います。以前にこの問題に直面したことがあり、LocationListenerの作成をサービスに移動することで解決しました。リスナーへの参照も保持してください。問題を解決できるかもしれません。

1
Toverbal