Flutter SDK: Dart とネイティブのブリッジング
Tracelet は、ほぼすべてのロジックをネイティブ iOS および Android SDK にプッシュするという点で独特です。なぜ?なぜなら、Dart アイソレーションは重く、ユーザーが一歩を踏み出すたびにバックグラウンドで Flutter エンジンを起動すると、バッテリー寿命が破壊されるからです。
このページでは、実際のシナリオで Flutter レイヤーがネイティブ エンジンとどのように対話するかを説明します。
シナリオ 1: UI サブスクリプション
検討した概念: イベント ストリーム、ヘッドレス実行
問題
あなたはフィットネス アプリを構築しています。ユーザーが画面を見ているときに、小さな青い点が Google マップ上でリアルタイムに移動するようにしたいとします。ユーザーが画面をロックしても、その実行をデータベースに記録する必要がありますが、誰も見ていない UI を更新する必要はありません。
Tracelet がそれを解決する方法
Tracelet は、ネイティブ トラッキング エンジンを Dart UI ストリームから分離します。
Tracelet.start() を呼び出すと、ネイティブ iOS/Android エンジンが起動します。モーション検出、GPS フィルタリング、SQLite 保存、HTTP 同期をすべて Swift/Kotlin で処理します。
Flutter UI では、ストリームをサブスクライブするだけです。
import 'package:tracelet/tracelet.dart' as tl;
void initializeTracking() async {
// 1. Listen to events in the UI
tl.Tracelet.onLocation((tl.Location location) {
print('Update UI map marker: ${location.coords.latitude}, ${location.coords.longitude}');
});
tl.Tracelet.onMotionChange((tl.Location location) {
print('User started/stopped moving: ${location.isMoving}');
});
// 2. Start the native engine
await tl.Tracelet.ready(tl.Config.balanced());
await tl.Tracelet.start();
}魔法: ユーザーがアプリを強制終了すると、onLocation Dart ストリームは停止します。 ただし、ネイティブの追跡エンジンは実行を続けます。 引き続き場所を SQLite に保存します。ユーザーが後でアプリを再度開くと、データベース アダプターを使用して SQLite データベースにクエリを実行し、ルートをレンダリングできます。
シナリオ 2: オンボーディング フロー
検討した概念: 許可の処理、拒否
問題
あなたは、高齢患者が徘徊を追跡するためのアプリを構築しています。 「常に」バックグラウンドでの位置情報の許可が必要です。システム許可ダイアログを単に彼らに投げると、彼らは混乱し、「拒否」をタップすると、アプリは使用できなくなります。
Tracelet がそれを解決する方法
Tracelet が自動的に権限を要求することは決してありません。 UI フローは完全に Flutter コードに任せられるため、恐ろしい OS プロンプトをトリガーする前に教育用のカスタム ダイアログを表示できます。
import 'package:tracelet/tracelet.dart' as tl;
// 1. Check current status
final status = await tl.Tracelet.requestLocationAuthorization();
// 2. The user permanently denied permission in the past
if (status == tl.AuthorizationStatus.deniedForever) {
// Show a beautifully designed Flutter dialog explaining WHY you need it.
// Add a button that calls:
await tl.Tracelet.openAppSettings();
return;
}
// 3. We haven't asked yet, or they selected "Ask Next Time"
if (status == tl.AuthorizationStatus.notDetermined || status == tl.AuthorizationStatus.denied) {
// Ask for foreground permission first
final result = await tl.Tracelet.requestLocationAuthorization();
if (result == tl.AuthorizationStatus.whenInUse) { // They granted "When In Use"
// Show a second Flutter dialog explaining why "Always" is needed.
// Then upgrade the permission:
await tl.Tracelet.requestLocationAuthorization();
}
} Location Status
Tracelet.requestLocationAuthorization() は AuthorizationStatus 列挙型を返します。
notDetermined: まだ質問していませんね。denied: ユーザーは拒否されました (Android では再度質問できます)。whenInUse: フォアグラウンドのみが許可されます。always: バックグラウンド アクセスが許可されました。deniedForever: ユーザーが「次回から質問しない」にチェックを入れたか、iOS が完全に拒否されました。それらを設定に送信する必要があります。