【挫折】React NativeでカーナビみたいなUIを実現してみる【未完】

メモです。でも結論からするとうまく行かずに挫折。この投稿はその失敗の記録である。

はじめに

タイトルどおりなんですが、Mapboxにはカーナビみたいなturn by turnのナビゲーションを実現するためのNavigation SDKというものが存在しています。でもiOSAndroid向けにしかありません。

今回はReact Nativeでナビゲーションを実装してみたかったのでいろいろと探してみるとやりたいことをやってくれているであろうOSSを発見しました。

github.com

個人の努力が公開されているのかと思いきやHOMEEというUSはシカゴにある企業のリポジトリでした。

最終的にこれを使うかはわからないのですがひとまず試してみることとします。

導入

パッケージのインストール自体はyarnで簡単にできるのですが、それを使えるようにするための作業がiOSAndroidそれぞれで必要になります。あと、実際に動かすにはMapboxのアクセストークンが必要です。

yarn add @homee/react-native-mapbox-navigation

iOSのほうがやることが多くて大変なのでまずは簡単なAndroidのほうから試します。

まずは最上位のgradle.propertiesでMapboxのシークレットトークンを指定します。

MAPBOX_DOWNLOADS_TOKEN= ここにシークレットトークン

そしてプロジェクトレベルのbuild.gradleに以下を追記。

allprojects {
    repositories {
        maven {
            url 'https://api.mapbox.com/downloads/v2/releases/maven'
            authentication {
                basic(BasicAuthentication)
            }
            credentials {
                // Do not change the username below.
                // This should always be `mapbox` (not your username).
                username = "mapbox"
                // Use the secret token you stored in gradle.properties as the password
                password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
            }
        }
    }
}

そしてandroid/app/src/main/AndroidManifest.xml<application></application>内に以下のようにパブリックトークンを指定します。

<meta-data android:name="MAPBOX_ACCESS_TOKEN"
    android:value="ここにパブリックトークン" />

サンプルコード

import * as React from "react";
import { StyleSheet, View } from "react-native";
import MapboxNavigation from "@homee/react-native-mapbox-navigation";

export const SomeComponent = () => {
  return (
    <View style={styles.container}>
      <MapboxNavigation
        origin={[-97.760288, 30.273566]}
        destination={[-97.918842, 30.494466]}
        shouldSimulateRoute
        showsEndOfRouteFeedback
        onLocationChange={(event) => {
          const { latitude, longitude } = event.nativeEvent;
        }}
        onRouteProgressChange={(event) => {
          const {
            distanceTraveled,
            durationRemaining,
            fractionTraveled,
            distanceRemaining,
          } = event.nativeEvent;
        }}
        onError={(event) => {
          const { message } = event.nativeEvent;
        }}
        onCancelNavigation={() => {
          // User tapped the "X" cancel button in the nav UI
          // or canceled via the OS system tray on android.
          // Do whatever you need to here.
        }}
        onArrive={() => {
          // Called when you arrive at the destination.
        }}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

実行するとこんなエラーが。

Invariant Violation: requireNativeComponent: "MapboxNavigation" was not found in the UIManager.

ググってもよくわからないが色々いじってるうちに解消。

続いてはこんなエラー

A problem occurred configuring project ':@homee_react-native-mapbox-navigation'.

Android Build Errors: maven plugin and compileSdkVersion · Issue #80 · homeeondemand/react-native-mapbox-navigation · GitHub

どうやらGradle7を使っているときにおきる問題らしく、6.9にダウンロードしてあげるといいって話があったのでそのあたりも試してみるがダメだ。

GitHubリポジトリを眺めていてふと気づいたのだがパッケージで入れるものはバージョンが1.1なのだけどリポジトリの最新リリースは2.0.0というのが存在している。これはどういうことかと思ったらどうやら前任の開発者がいなくなってしまい、npmorgのアクセス権がない状態になってしまっているようだ。なので新しいバージョンをパブリッシュできないということらしい。この時点で今後のメンテナンスについては一抹の不安がある。

それはともかく、というわけでnpmではなくGitHubから直接入れるようにpackage.jsonを書き直し。

今度はまたmavenの問題が出る。今度は@homme/react-native-mapbox-navigation/android/build.gradleの以下をmaven-publishに書き換える

今度は以下のメッセージ。成功までが遠い…

A problem occurred configuring project ':@homee_react-native-mapbox-navigation'.
> Configuration with name 'compile' not found.

ここで、結論から伝えると最終的にこの後も発生しまくった数々の問題を解決できずあいにく時間切れとなってしまった。主に発生した事象は以下のようなものでどれも一つ解決しては別の問題が発生する、もしくはこっちを解決すればあっちで問題が出るといったような形。

  • React Nativeのバージョンが0.68+だとgradle-pluginのバージョンは7+である必要があるが、react-native-mapbox-navigationは6.9でないとエラーが出る。そして使っているRNのバージョンは0.68.1だった
  • gradle-pluginを6.9にするためにReact Nativeをダウングレードしたらビルドすらできなくなった
  • react-native-mapbox-navigationのサンプルアプリはビルドできているのでそのbuild.gradlesettigs.gradleなんかを移植してみたところ、ビルドは通るようになったが当然ながら機能しない
  • 機能しない原因の多くはNativeModules関連。導入しているものたちの設定を少しずつ戻していくもののランタイムエラーが発生してしまう。例えばreact-native-safe-area-contextの場合はRNSafeAreaProviderがnot foundになる。こんなのが多数発生する。
  • さらにRNをダウングレードしたために0.68+での書き方や設定を取り除く逆マイグレーションが多数発生。辛い
  • そして別で利用しているreact-native-background-geolocationが依存するMapbox GLのバージョンとreact-native-mapbox-navigationが依存するMapbox GLのバージョンが干渉する

という感じであえなく時間切れで諦めることとなりました。

まとめ

このようにReact NativeはNative Modulesが絡むとはまりがちです。

これまでもカメラ周り、ストレージ周り、GPS周りとはまってきたのですが今回もはまりました。

また、有償サービスのモバイル向けSDKが提供されていたとしてもReact Native (Flutterもだとは思いますが)のようなクロスプラットフォーム向けのSDKは出ていないことも多いです。

この辺り手軽にiOS/Androidの両方に対応したアプリを作れる代わりに辛さのある部分です。

©Keisuke Nishitani, 2023   プライバシーポリシー