Skip to Content
はじめるフラッターSDK

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(); } }

Tracelet.requestLocationAuthorization()AuthorizationStatus 列挙型を返します。

  • notDetermined: まだ質問していませんね。
  • denied: ユーザーは拒否されました (Android では再度質問できます)。
  • whenInUse: フォアグラウンドのみが許可されます。
  • always: バックグラウンド アクセスが許可されました。
  • deniedForever: ユーザーが「次回から質問しない」にチェックを入れたか、iOS が完全に拒否されました。それらを設定に送信する必要があります。