[Xamarin] GEO Location, Android位置情報をゲット

今日はVisual Studio / Xamarin で Androidアプリを作っています。

# 現在地の取得

アプリの現在地を取得します。

参照にしたドキュメントはこちら
https://docs.microsoft.com/en-us/xamarin/essentials/geolocation?tabs=android

# パーミッションの設定

このアプリはロケーションを取得しますよ、という意思表示をします。いくつか方法はあるようですが、一番簡単なのはこれかな。Android アプリプロジェクトを右クリックして、プロジェクトプロパティからAndroidマニフェスト、必要なアクセス許可の一覧から必要なものをチェック。　ACCESS_FINE_LOCATIONとACCESS_COARSE_LOCATIONをチェックします。

>　right-click on the Android project and open the project's properties. Under Android Manifest find the Required permissions: area and check the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions. This will automatically update the AndroidManifest.xml file.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/fc5d2b95-8611-d0a6-09e0-ccc4950d86b6.png)

# Xamarin.Essentials

今回使うクラスはXamarin.Essentialsになるので、追加。

```csharp
using Xamarin.Essentials;
```

# Geolocation.GetLocationAsync で位置取得

すでにロケーションを取得している場合は`GetLastKnownLocationAsync`というメソッドがいいとのことですが、この値がキャッシュにない場合はNullが返ってくるとのことです。 今回は最新のロケーションをとりたいのでスキップします。

下記がロケーションゲットする部分のコードになります

```csharp
// Check For Permission
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == (int)Android.Content.PM.Permission.Granted){
  // We have permission, let's get current Location
  try{
    var request = new GeolocationRequest(GeolocationAccuracy.Medium);
    var location = await Geolocation.GetLocationAsync(request);

    if (location != null){
      // Set Location
      TextView currentLocationView = FindViewById<TextView>(Resource.Id.current_location);
      currentLocationView.Text = $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";
    }
  }
  catch (FeatureNotSupportedException fnsEx){
    // Handle not supported on device exception
    Console.WriteLine("Not Supported");
  }
  catch (FeatureNotEnabledException fneEx){
    // Handle not enabled on device exception
    Console.WriteLine("Not Enabled");
  }
  catch (PermissionException pEx){
    // Handle permission exception
    Console.WriteLine("No Permission");
  }
  catch (Exception ex){
  // Unable to get location
  Console.WriteLine("Grr Error");
  }
}
else{
  // Permission is not granted. If necessary display rationale & request.
  if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation)){
    // Provide an additional rationale to the user if the permission was not granted
    // and the user would benefit from additional context for the use of the permission.
    // For example if the user has previously denied the permission.
    Log.Info(TAG, "Get current location permission rationale to provide additional context.");

    var requiredPermissions = new System.String[] { Manifest.Permission.AccessFineLocation };
    Snackbar.Make(layout, Resource.String.permission_location_rationale, Snackbar.LengthIndefinite).SetAction(Resource.String.ok, new Action<View>(delegate (View obj) { ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION); })).Show();}
  else{
    ActivityCompat.RequestPermissions(this, new System.String[] { Manifest.Permission.AccessFineLocation }, REQUEST_LOCATION);}
}
```

# RUN

できました。

![Screenshot_20191109-134213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/e43b0e35-72d3-1e55-e0b1-7f010d2593f6.png)

# 粒度設定
さらに正確な位置を取得する場合はここを変更

```csharp
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
```

こちらを参考に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/4913a1f3-b6cf-a794-c820-b0a7cdcd1827.png)