web-dev-qa-db-ja.com

OnLocationChangedコールバックは呼び出されません

LocationManagerを使用してユーザーの現在位置を取得しようとしています。私は多くの研究を行ってきましたが、同じ問題を抱えている人を見つけることができないようです。 OnLocationChangedコールバックは呼び出されないようです。以下は私のさまざまなコードとlogcatです。

_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.dealsplus.app.NearbyItems$NearbyListFragment$MyLocationListener@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 Android.os.BinderProxy@47421a68}
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
_

そして、logcatのAndroid SDKロケーション部分は、それらを繰り返し繰り返します。私は考えることができるすべてを試し、グーグルとstackoverflowで見ました。また、サイドノートとして、API 9で利用可能なrequestSingleUpdateを使用し、ガイド に従って2.3デバイスで動作させることができました(== --- ==) Location になりますが、古いSDKを使用して2.1または2.2以上で動作する必要があります。 SOヒントがある場合、または詳細を知りたい場合はお知らせください。前もって感謝します。

61
smitt04

セットアップは機能するはずですが、機能しないため、トラブルシューティングのために例をできるだけ単純にします。私はあなたの要求を次のようにします

_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を使用する必要があり、送信を押すたびに1つのGPS更新を取得します。

59
Steve Blackwell

交換

LocationManager.GPS_PROVIDER

LocationManager.NETWORK_PROVIDER

私の問題を解決しました。

ここに私のロケーションマネージャーのコードスニペットがあります

 LocationManager locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);

//マシュマロ以上のロケーション許可を確認します

        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);
12
Hitesh Sahu

GPSプロバイダーは、デバイスが低電力の場合、または省電力モードを使用する場合、無効にします、その場合、onLocationChangedを受信できません

GPSプロバイダーほとんど戻りません家や建物の中にいる場合は場所を返します(屋外でのみ有効)

したがって、私のアプリでは、onLocationChanged()を受け取るために_GPS_PROVIDER_と_NETWORK_PROVIDER_の両方を使用します

https://developer.Android.com/guide/topics/location/strategies.html#Updates

GPSプロバイダーに位置の更新を要求するには、NETWORK_PROVIDERではなくGPS_PROVIDERを使用します。また、requestLocationUpdates()を2回(NETWORK_PROVIDERに対して1回、GPS_PROVIDERに対して1回)呼び出すことにより、GPSとネットワークロケーションプロバイダーの両方から位置の更新を要求することもできます。

8
Phan Van Linh

Steve Blackwellが書いたように、あなたのセットアップは良いです。あなたがcanしようとすることは、GPS固定信号を100%持っているかどうかを理解することです! Nice GPSテスターアプリケーション(Playストアから) をインストールしました。修正があるかどうか、どの衛星に接続しているか、接続強度はどれかを表示します。 OnLocationChanged()が呼び出されなかったのはこのためです。建物内から実行してみました:\

幸運を!

4
Li3ro

私は同じ状況にあったので、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. 
1
VyTcdc

そのような古いスレッドをぶつけてすみませんが、この質問はグーグル検索で比較的上位にランクされているので、これは他の人にとっては便利かもしれません。

同様の問題がありました。onlocationchangedが発生しませんでしたが、コードに問題はありませんでした。あらゆる種類の組み合わせを試した後、問題の根本的な原因は、サービスにリスナーを登録しているという事実であることに気付きました。

このサービスはフォアグラウンドサービスであったため、Googleに基づいて ドキュメント 動作するはずですが、DID NOT!

メソッドで初期化をラップし、サービスを作成またはバインドしたアクティビティからメソッドを呼び出すことで問題が解決しました。

これは私のサービスでの私の方法です:

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;

}
};

これがこの問題に出くわす他の人の助けになることを願っています。

1
Emil Borconi

同様の問題が発生しました。許可があり、サービスを正しく要求しましたが、更新はありませんでした。私がしなければならなかったのは、単に待つことだけでした。インターネットで問題を検索している間、アプリケーションを実行していましたが、数分後にアップデートを受信し始めました。その後、アプリを強制終了して再度実行しても、更新は即座に行われました-デバイスがまったく動いていないという事実のために、システムの問題であり、最適化であると思います、それはピクセルです)。

1
arenaq

なので Phan Van Linhが答えた、おそらくあなたが建物の中にいるからでしょう。説明があります こちら エミュレータ用にGPSをモックする方法について。また、GPSデータを模倣する this アプリがあります。

0
dafnahaktana

再起動するまで、実際のデバイス(M、アプリのtargetSDK 23)で同じ問題(NETWORK_PROVIDERで呼び出されなかったonLocationChanged())が発生しました。

0
Andrew Glukhoff

同じ問題に直面しました。 getLastKnownLocationがnullになっていた。デバイスとデバイスのロケーションサービスの両方を再起動すると、問題は解決します。

0
Niranjan
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);
        }
}
0
Reza

NETWORK_PROVIDERを使用している場合、テストするのは非常に困難です。

  • エミュレーター:動作しない
  • 実際のデバイスでは:getLastKnownLocation()のみが機能します。onLocationChanged()を受信するには、モバイルデータを使用し、強盗から電話を失うリスクがある外に出なければなりません:P

その理由は、デバイス自体ではなく、ネットワークプロバイダーの場所だけであり、ネットワークプロバイダーが移動することはないため、onLocationChanged()が呼び出されないためだと思います。モバイルデータとWi-Fi間での切り替え時のみに発生する可能性があります。間違っている場合は修正してください。

そのため、パフォーマンスとバッテリーの使用を検討する前に、GPS_PROVIDERを使用して実験することをお勧めします。エミュレータと実際のデバイスの両方でうまく機能します。ベストプラクティス: https://developer.Android.com/guide/topics/location/strategies.html

結果なしでNETWORK_PROVIDERでテストするのに数時間かかったので、うまくいけば私の提案が役に立ちました。

0
thanhbinh84

これは、電話の設定が原因で発生するはずです。電話機のロケーション設定で、ロケーションサービスモードがGPSのみに設定されている場合、GPS FixがあるときにOnLocationChangedコールバックがコールします。 [GPS、WI-FI、およびモバイルネットワークを使用する]オプションを選択すると、これら3つのプロバイダーを使用して場所が特定されます。これにより、デバイスの場所を見つけるのにかかる時間が短縮されます。 ***ロケーションサービスへのアクセスパスは、デバイスからデバイスに変更できます。ありがとう

0