RAKSUL TechBlog

ラクスルグループのエンジニアが技術トピックを発信するブログです

Firebase+React Nativeでつくったハコベルドライバーアプリの話

こんにちは。ハコベルの吉岡です。

ハコベルでは2019年2月に ハコベルコネクト をリリースしました。ハコベルコネクトは一般貨物 (大型トラックでの輸送をする業界) 向けのサービスで、運送業界をデジタル化していくためのプラットフォームとして、どんどん機能を追加していってる最中です。

提供する機能の一つにトラックの運転手の方に使ってもらうドライバーアプリがあります。今回はこのアプリについて紹介していこうと思います!ストアに公開しているので興味があれば是非覗いてみてください。 (運送業界の方しかアカウント開設できませんが。。)

App Store Google Play

背景

ドライバーアプリを使う最大のメリットは配車マンとドライバー間のコミュニケーションコストを削減できる点です。通常ドライバーは配車マンから運送案件の「指示書」を紙で受け取り、指示書の内容に沿って配送を行います。荷主からの指示内容の変更、渋滞などのトラブルでの遅延など、リアルタイムな情報共有が必要ですが、電話やチャットなどで情報を都度伝えているのが現状です。特に電話だと変更の内容は形に残らないし、今どこにいるのかも説明が難しかったりします。これらの課題を解決するために実装した機能をいくつか紹介します。

機能

通知

配車マンがドライバーに対して案件をアサインするとアプリがPush通知でそれを知らせます。ドライバーはアプリを開くと今まで指示書に記載されていた案件の内容がアプリから確認できます。案件内容に変更があるとこれまたPush通知でドライバーに知らされます。

動態管理

ドライバーアプリを使っていると、配送中はドライバーの位置を事務所にいるメンバーもリアルタイムに知ることができます。これにより渋滞やトラブルがあった際に効率よく情報を確認することができます。個々の配送案件の状況も見れるし、同じ事務所のドライバー全員の位置情報を見ることもできます。

書類アップロード

リアルタイムなやりとりとは毛色が違いますが、書類の管理もデジタル化できます。ドライバーが配送完了後に提出する書類は主に高速・駐車場代の領収書、配送完了を示す納品書ですが、こちらも紙でのやりとりが運送業界では主流です。ドライバーアプリではこういった書類をアプリで写真撮影して、そのままシステム上にアップロードすることができます。これもリアルタイムで内容確認できること、紛失など管理リスクが少なく便利になります。ペーパーレスを推進していきたいですね。また領収書から金額を読み取り、サジェストとして入力しておく機能もあります。

これらの機能を実現するのにどのような技術を使っているのか、どのようなサービスを活用しているのか気になってきたのではないでしょうか。この機会にその一部を紹介してみるので是非読み進めてみてください!

技術スタック

ハコベルコネクトのドライバーアプリではこのような技術スタックで開発してます。

  • React Native
  • Firebase
    • Realtime Database
    • Cloud Functions
  • Rails API

ドライバーアプリの開発時点では、アプリのエンジニアがチームにいませんでした。なのでWebアプリケーションをやってきたメンバーで開発を進めるにはどうするか検討し、React Nativeにチャレンジすることにしました。学習コストと開発スピード、内製で進めていける点でメリットがあるという判断でした。 (現在はアンドロイドの開発経験のあるエンジニアが1名います。引き続き積極採用中です!)

バックエンドとしてラクスルではAWSのサービスを使うことが多いのですが、今回実現したい機能やモバイルアプリ開発との親和性の高さから、Firebaseのサービスをいくつか使うことにしました。アプリに表示するためのデータはFirebase Realtime Databseで管理して、通知にはFirebase Cloud Messaging、データの処理などにはFirebase Cloud Functionsを利用しています。Realtime DatabaseとCloud Functionsについてはどう活用しているかについて後ほど詳しく紹介します。

Rails API

認証はOAuth 2.0のリソースオーナーパスワードクレデンシャルの仕組みを採用しています。サーバー側は Doorkeeper というGemを使って仕組みを構築しており、アプリからログインするとアクセストークンが返ってきます。ファイルのアップロードやマスターデータの更新に使っています。

アクセストークンと一緒にFirebaseにアクセスするためのトークンも一緒に返すようにしてます。やり方は DoorkeeperのWiki に説明があったのでそれに沿って実装しました。これがないとRealtime DatabaseのRead/Writeだったり、Cloud Functionsへのリクエストができません。Firebase用のトークンは仕様で有効期限が1時間となっているので、アクセストークンの再取得のタイミングもそれに合わせるようにしています。

Realtime Database

マスターデータ自体はRailsアプリケーション側のRDSにある状態で、ドライバーが見る必要があるデータだけをFirebase Realtime Databseに連携しています。今回Realtime Databaseを採用した理由としては、ネットワークの繋がらない環境でもある程度アプリを使えるようにしたかったからです。荷物の積み地や降ろし地が建物の地下にあって電波が入らない、なんてことは全然ありえる話です。

Firebase Realtime Databaseクライアントにはあらかじめデータをローカルのストレージに持って永続化する仕組みがあります。なのでオフラインになったとしてもローカルに保持しているデータを利用してオンラインの時と同じように動作させ続けることができます。

オフライン中に実行された書き込みのオペレーションのキューは自動的に保持されて、アプリがオンラインになったタイミングでサーバーに送信されます。

Androidでのオフライン機能の有効化 https://firebase.google.com/docs/database/android/offline-capabilities?hl=ja

Cloud Functions

アプリから送られてくる位置情報を受けてそれをRealtime Databaseに保存しています。ちなみに、配送中はアプリがフォアグラウンドにない場合も位置情報を取得する必要があるので、Background Geolocation というライブラリを使って対応しています。

送られてくる位置情報はログとしては問題ないのですが、それを地図上に表示する場合は補正が必要です。そのままプロットすると計測の誤差でギザギザになってしまったり、位置が前後したりします。その補正をするためにGoogleの Snap to Roads と呼ばれるAPIを利用しています。配送完了したタイミングでファンクションをトリガーして、Realtime Databaseに溜めてある位置情報をAPIになげます。 そうするとクレンジングされたデータが返ってくるので、それをまたRealtime Databaseに書き込んで、ユーザーに最終的に使うデータとして使用します。

生の位置情報を使ってプロットした場合

Snap to Roads後にプロットした場合

Cloud FunctionsはRealtime Databaseにあるデータを監視して、データが作成・更新・削除されたのをトリガーにファンクションを実行することもできます。前述したSnap to RoadsのAPIを叩く機能も、Realtime Databaseに保持された配送ステータスを監視して、それの更新をトリガーに実行しています。他にも、「集荷地に向かう」「着車」などのステータスも監視して、更新がされたらRailsのAPIにリクエストを送っています。

Databaseトリガー https://firebase.google.com/docs/functions/database-events?hl=ja

まとめ

このように、ドライバーアプリは様々な技術スタックをうまいこと組み合わせて使っています。アプリを作る際に少しでも参考になればいいです。今回紹介した機能以外にも工夫してるところはたくさんあるので、またの機会に紹介できればいいなと思っています。