0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

( ..)φメモメモ - Android アプリ内での通信手段

Posted at

通信手段 - IntentEventBusRemoteShareFlow

ここでは、 IntentEventBusRemoteShareFlow のそれぞれの特徴、利点、制約、具体的な使用例を挙げたうえで、詳細な使い分けを説明します。このような設計選択は、アプリケーションの効率性や拡張性に直接影響するため、重要です。

1. Intent

特徴

  • Androidフレームワークの基本的な通信手段:
    • コンポーネント間(アクティビティ、サービス、ブロードキャストレシーバーなど)の通信やアクション実行をトリガー。
  • 明示的 (Explicit) Intent暗黙的 (Implicit) Intent に分かれる:
    • 明示的Intent: 起動対象が明確(例: 特定のアクティビティやサービス)。
    • 暗黙的Intent: 起動対象をOSが判断(例: 他アプリでファイルを開く)。

利点

  1. システム統合:
    • ブロードキャストを利用してシステムイベント(例: ネットワーク接続変更、バッテリー低下)を送受信可能。
  2. シンプル:
    • キーバリュー形式で簡単にデータを渡せる。
  3. サービス/アクティビティ操作:
    • コンポーネントの起動や停止をトリガー。

制約

  • 状態管理に不向き:
    • Intentは状態を維持することができず、一度送信されたら終了。
  • 大量データの送受信は非効率:
    • Intentに格納できるデータ量は制限があり、メモリ消費も大きい。

使用例

  • アクティビティ遷移:
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("EXTRA_KEY", "value")
    startActivity(intent)
    
  • サービスの開始:
    val intent = Intent(this, MyService::class.java)
    startService(intent)
    

2. EventBus

特徴

  • パブリッシュ・サブスクライブ型通信:
    • イベントを発行元(Publisher)からリスナー(Subscriber)に非同期で伝達。
  • ローカル通信に特化:
    • アプリ内でのUIコンポーネント間通信やイベント通知に使用。

利点

  1. シンプルな設計:
    • イベントを発行・購読する仕組みが軽量かつ簡潔。
  2. リアルタイム性:
    • サブスクライバが即座にイベントを受け取る。
  3. 疎結合:
    • 発行元と受信先が直接依存しない設計。

制約

  • 大規模システムでは混乱の原因:
    • イベント数や種類が増えると、依存関係が不明瞭になる可能性がある。
  • ローカル通信限定:
    • プロセス間通信には対応していない。

使用例

  • UIの状態更新:
    EventBus.emit(MyEvent(data = "Update"))
    EventBus.observe<MyEvent> { event ->
        updateUI(event.data)
    }
    
  • センサーデータの通知:
    • センサーからリアルタイムで取得したデータをUIに反映。

3. RemoteShareFlow

特徴

  • プロセス間通信 (IPC) を活用した双方向通信:
    • Messenger を用いて、サービスとクライアント間でデータを送受信。
  • 状態とイベントの管理:
    • SharedFlow を使ったリアルタイムなデータフロー。

利点

  1. サービス依存型の状態管理:
    • サービスの状態をリモートで監視し、動的に更新。
  2. 双方向通信:
    • コマンド送信とその結果のレスポンス受信を同一のデータフローで管理。
  3. 長期タスクに最適:
    • フォアグラウンドサービスやバックグラウンド処理と強く連携。

制約

  • 実装が複雑:
    • Messengerの設定やライフサイクル管理が必要。
  • IPCのためのセットアップが必要:
    • クライアントとサービスをバインドする仕組みが前提。

使用例

  • サービス状態のリクエスト:
    remoteSharedFlow.emit(StrokeActivityStateAction())
    
  • リアルタイムイベントの受信:
    remoteSharedFlow.flow().collect { event ->
        handleRemoteEvent(event)
    }
    

使い分けの指針

Intentの適用領域

  • アクティビティ遷移、サービス開始、またはシステムイベントを処理する場合に使用。
  • 一度限りのデータ送信や明確なアクションが必要なケースに最適。

EventBusの適用領域

  • アプリ内の軽量で迅速な通信が必要な場合に使用。
  • ローカルなUI更新やセンサーデータの通知など、小規模のリアルタイムイベント。

RemoteShareFlowの適用領域

  • バックグラウンドで動作するリモートサービスとの通信や、サービスの状態管理を必要とするケースに最適。
  • 長期的にデータフローを監視したり、双方向で情報をやり取りする必要がある状況。

使い分けのまとめ

特徴 Intent EventBus RemoteShareFlow
用途 明確なアクション、コンポーネント間通信 ローカルなイベント通知、リアルタイム更新 サービスとクライアント間の双方向通信
通信対象 アクティビティ、サービス、ブロードキャスト UI、アクティビティ内部 フォアグラウンド/バックグラウンドサービス
リアルタイム性 低(アクションベース) 高(即座に伝達) 高(SharedFlowによる)
状態管理 不可 不可 可能
通信のスコープ アプリ内外のコンポーネント アプリ内 プロセス間通信

サービス - lib.service

lib.serviceパッケージは、リモートサービスの接続とイベント処理を効率的に行うための仕組みを提供しています。

サービスとの通信

StrokeActivityStateAction を例に、シーケンス図と詳細な説明を示します。この図は、イベントの生成、処理、レスポンスの流れを視覚的に表現します。

PlantUMLシーケンス図

説明

  1. ユーザーのアクション:

    • ユーザーがアクティビティ状態を確認したい場合、アプリに対してリクエストを送信します。
  2. RequestStrokeActivityState の呼び出し:

    • アプリケーションは RequestStrokeActivityState.invoke() を実行し、StrokeActivityStateAction を生成します。
    • このイベントオブジェクトはリモートサービスに送信されます。
  3. リモートサービスの処理:

    • RemoteEventServiceStrokeActivityStateAction を受け取り、内部でDataRepositoryに問い合わせを行い、現在のアクティビティ状態 (isInActivity) を取得します。
  4. レスポンス生成:

    • RemoteEventServiceisInActivity の結果を基に StrokeActivityStateAction を更新し、それをレスポンスとして返します。
  5. レスポンスの処理:

    • リモートサービスマネージャ (RemoteServiceManager) は返された状態データ (isInActivity) をアプリに通知します。
    • アプリケーション側でこのデータを利用して必要なアクションを実行できます。

活用場面

この流れは、アプリケーションがリモートサービスと連携して動作状況を管理する場面で役立ちます。例えば:

  • アクティビティが現在アクティブかどうかを確認する。
  • 状態に応じてUIやロジックを変更する。

フォアグランドサービスの起動と停止

次の図は、サービスの開始・停止時に関与する主要な要素を示します。

説明

  1. 起動:

    • launchServiceInForeground()を呼び出すことで、通知チャンネルの生成と通知の表示を通じてサービスがフォアグラウンドモードに移行します。
    • RemoteEventService内でstartForeground(notificationId)が実行されます。
  2. 停止:

    • terminateForegroundService()を呼び出すことで、通知がクリアされ、サービスはバックグラウンドまたは終了状態になります。
    • RemoteEventService内でstopForeground()stopSelf()が実行されます。

全体の機能概要

1. リモート通信を支える主要な仕組み

  • RemoteSharedFlow:
    • リモートイベントの双方向通信を可能にする。
    • コルーチンやSharedFlowを使用して非同期データストリームを提供。
    • サービスのバインディング (bindService) と解除 (unbindService) を簡単に管理。

2. サービスライフサイクル管理

  • RemoteEventService:
    • AndroidのLifecycleServiceを拡張し、リモートイベントの処理を統一的に管理。
    • フォアグラウンドサービスとして動作し、ユーザー通知を表示する機能。
    • イベントストリーム (flow) をリアルタイムで監視し、カスタムロジックを実行可能。

3. ユーティリティクラスでの一元管理

  • RemoteServiceManager:
    • リモートサービス接続 (connectToRemoteService) と切断 (disconnectFromRemoteService) を一元管理。
    • サービスコマンドを送信 (sendServiceCommand) し、アクション (ACTION_FOREGROUND_STARTなど) を実行可能。
    • 他のクラスやコンポーネントが簡単にリモート通信を利用できるAPIを提供。

4. 拡張機能と便利なヘルパーメソッド

  • 背景でのイベント処理:
    • observeServiceActions でリモートイベントの監視。
    • dispatchServiceEvent を使ってリモートイベントの送信。
  • フォアグラウンドサービス操作:
    • launchServiceInForeground でフォアグラウンドサービス開始。
    • terminateForegroundService でフォアグラウンドサービス終了。

利用の全体的な流れ

  1. サービス接続:
    • startServiceConnection を呼び出してサービスを接続。
  2. イベント処理:
    • observeServiceActions でイベントを監視し、必要に応じてカスタムロジックを追加。
    • dispatchServiceEvent でイベントをリモートサービスに送信。
  3. フォアグラウンド化:
    • 必要に応じて launchServiceInForeground でフォアグラウンドサービスを起動し、継続的に動作させる。
  4. サービス終了:
    • terminateForegroundServicestopServiceConnection を呼び出してサービスを終了。

データ処理の関連図

モジュール間の通信

モジュール間の通信は、EventBusもしくはIntentを通じて行います。

DataProcessorとの通信(EventBus)

DataProcessorとの通信は、EventBusを使用します。

サービス間の通信(Usecaseパターン)

Activity, Notification, Service間の通信(制御)は、IntentやFlowを使用します。
Usecaseパターンで、通信の実装を隠蔽します。

リポジトリパターン - Service/Repository/Procec

全体の仕組み概要

  1. DataSource:

    • センサーやファイルシステムなど、外部リソースに直接アクセスし、データを取得します。
    • 取得したデータを非同期ストリームとして提供し、Flow<T>を返します。
  2. DataProcessor:

    • 一つまたは複数のDataSourceを管理・制御します。
    • 必要なデータを統合・加工し、データ処理のロジックを定義します。
    • EventBusを通じてイベントの送受信を行います。
  3. DataRepository:

    • DataProcessorをさらに管理・制御します。
    • アプリケーションの他の部分と連携し、データの取得、処理、提供を統括します。
    • startstopを通じてデータ処理タスクのライフサイクルを管理します。

repo

service

lib

イベントバス - lib.event, lib.eventbus

lib.event パッケージは、SensingEvent とその派生クラス SensingDataSensingActionSensingParam を提供し、これらは CsvSerializable を継承してCSV形式にシリアライズ可能です。
また、lib.eventbus パッケージは、イベントの発行と監視を行う EventBus クラス、イベントハンドラのインターフェース EventBusHandlerSensingEvent 型のイベントを扱う SensingEventBusHandler とその実装 SensingEventBusHandlerImpl、およびインスタンス生成を行う EventBusFactory を含みます。

クラス図の説明

  1. EventBus クラス

    • EventBusはイベントを管理するクラスです。
    • 内部にMutableSharedFlow<Any>型の_eventsを持ち、外部にはSharedFlow<Any>型のeventsを公開しています。
    • emitメソッドでイベントを発行し、observeメソッドでイベントを監視します。
  2. EventBusHandler インターフェース

    • ジェネリック型Tを持つイベントハンドラのインターフェースです。
    • emitEventメソッドでイベントを発行し、observeEventメソッドでイベントを監視します。
  3. SensingEventBusHandler インターフェース

    • EventBusHandler<SensingEvent>を継承したインターフェースです。
    • SensingEvent型のイベントを扱います。
  4. SensingEventBusHandlerImpl クラス

    • SensingEventBusHandlerインターフェースを実装したクラスです。
    • CoroutineScopeを使用して非同期にイベントを発行および監視します。
  5. EventBusFactory オブジェクト

    • SensingEventBusHandlerのインスタンスを生成するファクトリクラスです。
    • カスタムプロバイダを設定したり、リセットしたりするメソッドを持ちます。
  6. SensingEvent クラス

    • CsvSerializableを継承した抽象クラスです。
    • タイムスタンプを持つイベントの基底クラスです。
  7. SensingData, SensingAction, SensingParam クラス

    • SensingEventを継承した抽象クラスです。
    • それぞれ異なる種類のセンシングイベントを表します。
  8. CsvSerializable クラス

    • フィールド値をCSV形式に変換するための抽象クラスです。
    • toFieldValuesメソッドを持ち、クラスのフィールド値をリストとして返します。

シリアライゼーション - lib.serialization

lib.serializationは、CsvSerializableを継承したデータクラスをCSV(文字列)にシリアライズしたりデシリアライズしたりするパッケージです。

クラス図の説明

  1. CsvSerializable クラス

    • 抽象クラスであり、toFieldValues メソッドを持っています
    • ClassTag アノテーションを持っています
  2. ClassTagRegistry オブジェクト

    • クラスとタグのマッピングを管理するためのオブジェクトです
    • クラスとタグのマッピングを保持する2つのマップ (classToTagMaptagToClassMap) を持っています
    • クラスとタグを登録・取得するためのメソッドを提供します
  3. CsvHandler オブジェクト

    • CSVシリアライズとデシリアライズを行うためのオブジェクトです
    • クラスを登録するメソッド (addCsvSerializable) や、オブジェクトをCSVに変換するメソッド (convertObjectToCsv)、CSVをオブジェクトに変換するメソッド (convertCsvToObject) を持っています
    • 型に基づいて値を解決するためのリゾルバ (TypeBasedValueResolver) を追加するメソッドを持っています

関係

  • CsvHandlerClassTagRegistry を使用してクラスの登録やタグの取得を行います
  • CsvHandlerCsvSerializable を使用してオブジェクトのシリアライズとデシリアライズを行います
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?