はじめに:ORPHE TRACKの技術前提
ORPHE TRACK は、以下の “3つのリアルタイム処理” を同時に実行するアプリです。
※ORPHE TRACKの構成&動作イメージ
- BLE センサー(ORPHE CORE)からのランニングデータ取得
- スマートフォンの位置情報(GPS)取得
- 音声フィードバックの再生(通常音声 + AI 音声)
これらは バックグラウンド状態でも同時に継続動作する必要があります。
しかし iOS / Android ともに、
バックグラウンド動作には OS レベルで強い制約があります。
そのため、初期段階では 20分程度でアプリが停止するという課題がありました。
本記事群では、
ORPHE TRACK の開発を通じて得た「バックグラウンド動作を安定化するための知見」をまとめています。
ORPHE TRACK のアーキテクチャ(全体構成)
+------------------------------------------------------------+
| ORPHE TRACK(Flutter) |
+------------------------------------------------------------+
| UI / 状態管理 |
| - 計測画面 / マップ画面 / 設定画面 など |
+------------------------------------------------------------+
| アプリロジック層 |
| - BLE処理:COREからのリアルタイムデータ取得 |
| - 位置情報処理:geolocator(GPS, distanceFilter=10m) |
| - 音声処理:video_player / audioplayers / flutter_tts |
+------------------------------------------------------------+
| バックグラウンドサービス |
| - flutter_background_service |
| - Android: フォアグラウンドサービス |
| - iOS: background_fetch は無効(30秒で停止するため) |
| - バックグラウンド専用タイマー |
+------------------------------------------------------------+
| データ保存 |
| - 通常時: masamune(DB) |
| - BG時: shared_preferences(軽量バッファ) |
| → 復帰時に masamune へ復元 |
+------------------------------------------------------------+
| 外部要素 |
| - CORE(BLEセンサー) |
| - iOS / Android OS(バックグラウンド制約) |
+------------------------------------------------------------+
内部モジュールのデータフロー
+--------------------+
| CORE(センサー) |
+----------+---------+
|
| BLE
v
+------------------------+ +----------------------+
| BLEモジュール | | 位置情報モジュール |
| (接続 / データ取得) | | (GPS / geolocator)|
+-----------+------------+ +----------+-----------+
| |
| ランデータ | 緯度経度
v v
+---------------------------+ +---------------------------+
| 計測ロジック(統合) | | マップ表示 / 距離算出 |
+---------------------------+ +---------------------------+
| |
| |
+------------+-------------+
|
v
+-------------------+
| データ保存層 |
| masamune / shared |
+-------------------+
|
v
+-------------------+
| 可視化 / レポート |
+-------------------+
バックグラウンド動作で特に問題になった3点
-
OSがバックグラウンド処理を積極的に停止する問題
(flutter_background_service で継続タスクを構築)
-
GPSの消費電力が大きく、OSにより強制停止される問題
(GPS粒度の最適化:distanceFilter を 10m へ)
-
音声再生が他アプリの音楽と競合し、勝手に音楽が停止する問題
(各ライブラリごとの“mixWithOthers / duckOthers”挙動の調整)
90分動作達成までの改善プロセス
ステップ0:初期状態
+---------------------------------------+
| - Flutter標準タイマーで計測 |
| - GPS高精度 / distanceFilter=0m |
| - DBへ直接保存 |
| → 20分前後でBG停止 |
+---------------------------------------+
ステップ1:バックグラウンドサービス導入
+---------------------------------------+
| - flutter_background_service 導入 |
| - BG側でタイマーを回すように変更 |
| - iOSのbackground_fetchは無効化 |
| → 動作は安定するが、まだ停止リスク有 |
+---------------------------------------+
ステップ2:位置情報の粒度調整
+-----------------------------------------+
| - LocationAccuracy / distanceFilter見直し|
| - distanceFilterを10mに設定 |
| → 電池消耗が大きく低減 |
| → OSによる強制停止がほぼ発生しない |
+-----------------------------------------+
ステップ3:保存処理の軽量化
+---------------------------------------+
| - BG中は shared_preferences に保存 |
| - 復帰時に masamune に復元 |
| → 重い書き込み処理をBGから排除 |
+---------------------------------------+
最終状態
+---------------------------------------+
| - 実測で最大約90分の連続計測を確認 |
| - ランニング用途として実用的な安定性 |
+---------------------------------------+
記事構成
-
記事1:OS制約の突破とバックグラウンドサービスの安定化
https://qiita.com/aktouch/items/fa3f5d4ec9dcc073ff7e -
記事2:GPS位置情報の最適化と消費電力対策
https://qiita.com/aktouch/items/ac95eafb1cc4f8e58c41 -
記事3:音声再生と他アプリの競合を解決する方法
https://qiita.com/aktouch/items/6ce96465a8e86b9db95a
