1. ホーム
  2. android

[解決済み] Android : LocationManagerとGoogle Play Servicesの比較

2022-04-23 06:43:17

質問

ユーザーの現在地を取得し、そのユーザーの近くにあるバーやレストランなどの観光スポットを検索するアプリを作りたい。 Google Places API .

ウェブで検索してみると、このチュートリアルの中で LocationManager クラスを使用するものと Google Play サービス を使用することで、ユーザーの位置を特定することができます。

一見すると、どちらも同じことをやっているように見えますが、私は初めてなので、少し混乱してしまい、どの方法が私のニーズに最も合っているのか分かりません。だから、私はあなたに聞きたい。

この2つの位置情報検索方法の違いは何ですか(もしあれば)?

どのように解決するのですか?

Androidのユーザー位置情報

Androidでのユーザーの位置情報の取得は、iOSの場合よりも少し簡単ではありません。混乱の始まりは、2つの全く異なる方法があることです。1つ目は、AndroidのAPIを使用して android.location.LocationListener もう一つはGoogle Play ServicesのAPIを使用する方法です。 com.google.android.gms.location.LocationListener . では、両方を見てみましょう。

  1. Androidの位置情報API

    Androidの位置情報APIは、位置情報を取得するために3つの異なるプロバイダを使用しています。

    • LocationManager.GPS_PROVIDER - 人工衛星を利用して位置を特定するプロバイダです。状況により、位置情報の取得に時間がかかる場合があります。
    • LocationManager.NETWORK_PROVIDER - セルタワーやWiFiのアクセスポイントの有無から位置を特定するプロバイダです。結果はネットワークルックアップによって取得される。
    • LocationManager.PASSIVE_PROVIDER - このプロバイダは、他のプロバイダが生成した位置を返します。他のアプリケーションやサービスが位置情報の更新を要求したときに、実際に自分で位置情報を要求することなく、受動的に位置情報の更新を受け取ることができます。

のオブジェクトを取得するというのがミソです。 LocationManager を実装し、システムから LocationListener を呼び出す。 requestLocationUpdates の上で LocationManager .

以下は、コードスニペットです。

    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

Googleの位置情報戦略に関するAPIガイド は、このコードをとてもうまく説明しています。しかし、ほとんどの場合、バッテリーのパフォーマンスが向上し、より適切な精度を得ることができるのは Google Location Services API 代わりに さあ、混乱の始まりです

  1. Googleの位置情報サービスAPI

Google の Location Services API は、Google Play Services APK ( 設定方法はこちら ) . これらは、AndroidのAPIの上に構築されています。これらのAPIは、上記のプロバイダーの代わりに「Fused Location Provider」を提供します。このプロバイダーは、精度やバッテリー使用量などに基づいて、どの基礎プロバイダーを使用するかを自動的に選択します。常に更新されるシステム全体のサービスから位置情報を取得するため、高速に動作します。そして、ジオフェンシングなど、より高度な機能を使うことができます。

Googleの位置情報サービスを利用するためには、アプリから GooglePlayServicesClient . クライアントに接続するには、アクティビティ(またはフラグメントなど)に GooglePlayServicesClient.ConnectionCallbacksGooglePlayServicesClient.OnConnectionFailedListener のインターフェイスを使用します。 以下はサンプルコードです。

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        locationClient = new LocationClient(this, this, this);
    }

    @Override
    public void onConnected(Bundle bundle) {
    Location location = locationClient.getLastLocation() ;
        Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDisconnected() {
    Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // code to handle failed connection
        // this code can be found here — http://developer.android.com/training/location/retrieve-current.html 
    }

  • なぜ locationClient.getLastLocation() null?

locationClient.getLastLocation() はクライアントから最後の既知の位置を取得します。しかし、Fused Location Providerは、少なくとも1つのクライアントが接続されている場合にのみ、バックグラウンドの位置情報を保持します。最初のクライアントが接続すると、それは直ちに位置情報を取得しようとします。もしあなたのアクティビティが最初に接続したクライアントで、あなたが getLastLocation() ですぐに onConnected() の場合、最初の位置が来るまでに時間が足りないかもしれません。その結果 location である null .

この問題を解決するには、プロバイダが位置を取得するまで(不確定に)待ち、その後に getLastLocation() を知ることは不可能です。もう一つの(より良い)選択肢は com.google.android.gms.location.LocationListener インターフェイスを使用して、定期的な位置情報の更新を受信します(最初の更新を受信したらスイッチをオフにします)。

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    // . . . . . . . . more stuff here 
    LocationRequest locationRequest;
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // . . . . other initialization code
        locationClient = new LocationClient(this, this, this);
    locationRequest = new LocationRequest();
    // Use high accuracy
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the update interval to 5 seconds
    locationRequest.setInterval(UPDATE_INTERVAL);
        // Set the fastest update interval to 1 second
    locationRequest.setFastestInterval(FASTEST_INTERVAL);
    }
    // . . . . . . . . other methods 
    @Override
    public void onConnected(Bundle bundle) {
        Location location = locationClient.getLastLocation();
        if (location == null)
            locationClient.requestLocationUpdates(locationRequest, this);
        else
            Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
    }
    // . . . . . . . . other methods
    @Override
    public void onLocationChanged(Location location) {
        locationClient.removeLocationUpdates(this);
        // Use the location here!!!
    }

このコードでは、クライアントがすでに最後の位置( onConnected ). もしそうでなければ、位置情報の更新を要求し、その要求をオフにします ( onLocationChanged() コールバック) を使用します。

なお locationClient.requestLocationUpdates(locationRequest, this); の中になければなりません。 onConnected のコールバックが発生します。 IllegalStateException Google Play Services Clientに接続していない状態で位置情報を要求しようとしているためです。

  • ユーザーが位置情報サービスを無効にしている

多くの場合、ユーザーは位置情報サービスを(バッテリーの節約やプライバシー上の理由から)無効にしています。そのような場合、上記のコードでは位置情報の更新を要求することになりますが onLocationChanged が呼び出されることはありません。ユーザーが位置情報サービスを無効にしているかどうかを確認することで、要求を停止することができます。

アプリで位置情報サービスを有効にするよう要求された場合、メッセージや乾杯の音頭を表示したいものです。残念ながら、GoogleのLocation Services APIには、ユーザーが位置情報サービスを無効にしているかどうかを確認する方法がありません。そのため、AndroidのAPIに頼る必要があります。

において onCreate メソッドを使用します。

    LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
    locationEnabled = false;
    Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;

そして locationEnabled フラグを onConnected メソッドをこのように使用します。

    if (location != null) {
    Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
    locationClient.requestLocationUpdates(locationRequest, this);
}

アップデイト

ドキュメントが更新され、LocationClientが削除され、ダイアログからワンクリックでGPSを有効にすることができるようになりました。

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

リンク https://developer.android.com/training/location/change-location-settings#prompt

新しい位置情報クライアントです。FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

を経由することが推奨されます。 https://developer.android.com/training/location ロケ作業をする前に