React Nativeでバックグラウンド位置情報 + Geofence

# やりたいこと
今回はReact Nativeアプリにおいて、Geofenceを使用し、特定の場所に出入りした際に情報をサーバーに飛ばしてステータスを変更するために導入を行いました。

Geofenceを使用するためには、アプリがバックグラウンド位置情報（Always）が実行できる状態にある必要があります。

イメージ
![68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f36303969696272366f667a6f7137702f53637265656e73686f74253230323031352d30362d303625323031372e30352e33332e706e673f646c3d31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/c32e077a-b5cf-7f4a-f8ab-b549348052f8.png)


# 使用ライブラリ
react-native-background-geolocation
https://github.com/transistorsoft/react-native-background-geolocation

Android版は有料なので注意。
どうしても無料で使いたい場合は、こちらを使用しましょう。
https://github.com/mauron85/react-native-background-geolocation

# 導入（iOS）
0.60以上を想定しています。
公式のセットアップドキュメントはこちら
iOS: https://github.com/transistorsoft/react-native-background-geolocation/blob/master/help/INSTALL-IOS-AUTO.md
Android: https://github.com/transistorsoft/react-native-background-geolocation/blob/master/help/INSTALL-ANDROID-AUTO.md

### パッケージのインストール

```
yarn add react-native-background-geolocation
```

### Xcodeでの設定

<img width="960" alt="68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f6134786965796430683338786b6c752f53637265656e73686f74253230323031362d30392d323225323030382e31322e35312e706e673f646c3d31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/13dee069-e2aa-58dd-4e60-f2a7f7ed47f5.png">
Audio, Location updates, Background fetchを有効にする

### Info.plist
<img width="865" alt="スクリーンショット 2020-05-09 0.10.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/86e7ceae-e974-9ce6-f12d-90b321ac3ddf.png">


# アプリでの実装

```jsx
import BackgroundGeolocation, { Geofence } from "react-native-background-geolocation";

    ...
    BackgroundGeolocation.ready({
      // Geolocation設定
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      distanceFilter: 10,
      stopTimeout: 1,
      debug: true, 
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      stopOnTerminate: false,  
      startOnBoot: true, 
      batchSync: false, 
      autoSync: true
    }, (state) => {
      console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);

      if (!state.enabled) {
        BackgroundGeolocation.start(function() {
          console.log("- Start success");
        });
      }
    });

    BackgroundGeolocation.addGeofence({
        identifier: "Home",
        radius: 200,
        latitude: 47.2342323,
        longitude: -57.342342,
        notifyOnEntry: true
    });
    
    BackgroundGeolocation.onGeofence(function(geofence, taskId) {
        this.handleWithGeofenceLocation(geofence.location)
        BackgroundGeolocation.finish(taskId);
    });

    BackgroundGeolocation.removeGeofence("Home");

```

開発の際はdebugモードで確認すると音とアラートで動いているかどうかを確認できます。

# Tips
### サンプルアプリ（公式）
https://github.com/transistorsoft/rn-background-geolocation-demo

パラメータなどが複雑なため、理解するためにサンプルアプリを触ってみることをお勧めします。

### Geofenceの制限
Geofenceの数については、iOSは20つ、Androidは100つまでという制限があります。

# まとめ
何度か使ったことがあり、問題が多いイメージのreact-native-background-geolocationですが、最新バージョンで改めて導入をしたところかなりスムーズに進みました。Ver 3.6.0以上であればreact-native-background-fetchも必要なくなっています。

時間があったらGeofence以外の部分も研究してみようと思います。