React Nativeは、Web上でネイティブな GeolocationAPIを利用します。 このAPIは、ReactNativeポリフィルで使用可能なgetCurrentPositionwatchPositionなどのさまざまなメソッドを返します。 React Nativeアプリでの使用方法を示すために、react-native-cliを使用して統合します。

入門

react-native-cliを使用するということは、テンプレートがなく、開始するための定型コードがほとんどないことを意味します。 次のコマンドを使用してプロジェクトを生成します。 ローカルマシンにまだインストールしていない場合は、以下に示す最初のコマンドを使用してください。

# to install the cli
$ npm install -g react-native-cli

# to scafold an RN project
$ react-native init geo-example

したがって、プロジェクトディレクトリが生成されたら、そのディレクトリに移動してnpm startを実行し、すべてが正しくインストールされているかどうかを確認します。 Macを使用している場合は、iosシミュレータを使用して確認できます。 WindowsおよびLinuxユーザーの場合、Androidエミュレーターが友だちになります。

GeolocationAPIへのアクセス

Geolocation APIは、Webと同様に、ReactNativeにグローバルnavigatorオブジェクトとして存在します。 ソースコードのnavigator.geolocationからアクセスでき、インポートする必要はありません。

デモンストレーションの目的で、GeolocationAPIのgetCurrentPositionメソッドを使用します。 このメソッドを使用すると、モバイルアプリはユーザーの場所を要求し、成功コールバック、エラーコールバック、構成オブジェクトの3つのパラメーターを受け入れることができます。

navigator.geolocation.getCurrentPosition(
  position => {
    const location = JSON.stringify(position);

    this.setState({ location });
  },
  error => Alert.alert(error.message),
  { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);

上記の成功コールバックにはposition引数があり、エラーなしで実行された場合、次のプロパティを持つオブジェクトになります。

{
  "timestamp": 1533729980953.91
  "coords": {
    "accuracy": 5,
    "altitude": 0,
    "altitudeAccuracy": -1,
    "heading": -1,
    "latitude": 37.785834,
    "longitude": -122.406417,
    "speed": -1
  }
}

開始するには、ReactNativeプロジェクトのApp.jsを変更します。 まず、テキストFind My Coords?を表示する基本的なクラスコンポーネントを定義します。

App.js
import React, { Component } from "react";
import { View, Text } from "react-native";

export default class App extends Component {
  render() {
    return (
      <View>
        <Text>Find My Coords?</Text>
      </View>
    );
  }
}

GeolocationAPIの実装

それでは、GeolocationAPI関数getCurrentPositionをアプリに実装しましょう。 App.jsを開き、次のコードを記述します。

App.js
import React, { Component } from "react";
import {
  Platform,
  StyleSheet,
  Text,
  View,
  Alert,
  TouchableOpacity
} from "react-native";

export default class App extends Component {
  state = {
    location: null
  };

  findCoordinates = () => {
    navigator.geolocation.getCurrentPosition(
      position => {
        const location = JSON.stringify(position);

        this.setState({ location });
      },
      error => Alert.alert(error.message),
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
    );
  };

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={this.findCoordinates}>
          <Text style={styles.welcome}>Find My Coords?</Text>
          <Text>Location: {this.state.location}</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

TouchableOpacityのインポートを開始します。 これは、ユーザーのタッチに正確に応答するラッパーです。 React Nativeモバイルアプリでは、そのラッパーコンポーネントを頻繁に使用します。 Webアプリケーションのボタンと考えてください。 この新しくインポートされたラッパーは、指定されたメソッド(この場合はfindCoordinates)をトリガーするonPressプロップを受け入れます。

findCoordinatesは、ユーザーの場所を取得するためのロジックを保持します。 また、ローカル状態を使用して、位置オブジェクトによって提供されたデータから座標を表示しています。 テキストFind My Coords?をクリックできるようになりました。

ReactNativeのStyleSheetを使用して少しスタイルを整えましょう。

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  },
  welcome: {
    fontSize: 20,
    textAlign: "center",
    margin: 10
  },
  instructions: {
    textAlign: "center",
    color: "#333333",
    marginBottom: 5
  }
});

この時点では、例は期待どおりに機能しません。 ユーザーの場所にアクセスするための許可を求める必要があります。 次にそれを修正しましょう。

許可を求める

iOSでは、react-native-cliを使用してプロジェクトを作成すると、ジオロケーションがデフォルトで有効になります。 これを使用するには、ios/findCoordsAppディレクトリ内にあるinfo.plistファイルに<key>NSLocationWhenInUseUsageDescription</key>というキーを含める必要があります。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>
    <key>CFBundleDisplayName</key>
    <string>findCoordsApp</string>
    [..]
    <key>NSLocationWhenInUseUsageDescription</key>
    <string></string>
    <key>NSAppTransportSecurity</key>
    <!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
  [...]
</dict>
</plist>

Androidの場合、android/app/src/AndroidManifest.xmlに次の行を追加する必要があります。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

まとめ

これで、アプリケーションを実行すると、次の画面が表示されます。

Screen before coordinates

テキストをクリックすると、アプリケーションがユーザーの場所を要求することを許可するかどうかを尋ねられます。

Screen asking permission

[許可]を押すと、次の画面が表示されます。

Screen with coordinates

これは非常に単純な例でしたが、そこからさらに興味深い/便利なものを作成することができます。 ReactNativeアプリケーションでのGeolocationAPIの操作について詳しく知りたい場合は、公式のドキュメントを参照してください。