[解決済み] Android : LocationManagerとGoogle Play Servicesの比較
質問
ユーザーの現在地を取得し、そのユーザーの近くにあるバーやレストランなどの観光スポットを検索するアプリを作りたい。 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
. では、両方を見てみましょう。
-
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
代わりに さあ、混乱の始まりです
- Googleの位置情報サービスAPI
Google の Location Services API は、Google Play Services APK ( 設定方法はこちら ) . これらは、AndroidのAPIの上に構築されています。これらのAPIは、上記のプロバイダーの代わりに「Fused Location Provider」を提供します。このプロバイダーは、精度やバッテリー使用量などに基づいて、どの基礎プロバイダーを使用するかを自動的に選択します。常に更新されるシステム全体のサービスから位置情報を取得するため、高速に動作します。そして、ジオフェンシングなど、より高度な機能を使うことができます。
Googleの位置情報サービスを利用するためには、アプリから
GooglePlayServicesClient
. クライアントに接続するには、アクティビティ(またはフラグメントなど)に
GooglePlayServicesClient.ConnectionCallbacks
と
GooglePlayServicesClient.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 ロケ作業をする前に
関連
-
aapt2エラー:ログを確認する(具体的な原因の探り方)
-
指定された子にはすでに親がいます。まず、その子の親に対して removeView() をコールする必要があります。
-
WeChatとQQは、他のアプリのオープンリストに自分のアプリを追加し、ファイルパスを取得することができます
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] Androidの「コンテキスト」とは何ですか?
-
[解決済み] AndroidでPythonを実行する方法はありますか?
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] EclipseのAndroidプラグインで "Debug certificate expired "エラーが発生する。
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
GIF、Lottie、SVGA
-
アンドロイドプロジェクトのパッケージングにgradleを使用する際の問題点
-
アプリケーションがメインスレッドで過剰に作業している可能性があります。
-
android block certificate validation CertPathValidatorException: 認証パスのトラストアンカーが見つかりません
-
Androidプロセス生存のためのソリューション
-
android bluetooth--Bluetooth on、検索、ペアリング、接続
-
Android基本アプレット
-
Androidカスタムドロップダウンリストボックスコントロール
-
アンドロイドにおけるトークンの利用
-
Android studio 制約レイアウト ConstraintLayout