1. ホーム
  2. アンドロイド

[解決済み】AndroidサービスがActivityと通信する方法

2022-04-03 04:19:59

質問

初めてAndroidアプリケーションを作成し、サービスとアクティビティ間の通信について理解しようとしています。バックグラウンドで動作し、GPSと時間ベースのロギングを行うサービスを持っています。サービスの開始と停止に使用されるアクティビティがあります。

そこでまず、アクティビティが開始されたときにサービスが実行されているかどうかを把握できるようにする必要があります。それについては、ここに他の質問があるので、私はそれを理解できると思います(しかし、自由にアドバイスを提供してください)。

私の本当の問題は、アクティビティが実行されていて、サービスが開始された場合、サービスがアクティビティにメッセージを送信する方法が必要なことです。現時点では単純な文字列と整数値で、主にステータスメッセージです。メッセージは定期的に発生するものではないので、他の方法があれば、サービスをポーリングするのは良い方法とは思えません。この通信は、Activityがユーザーによって開始されたときだけにしてほしいのです。つまり、Activityを開始し、Serviceが動作している場合、何か面白いことが起こるとActivity UIにステータスメッセージが表示されます。Activityを開始しない場合、これらのメッセージは表示されません(それほど面白いものではありません)。

サービスが稼働しているかどうかを判断し、稼働していればActivityをリスナーとして追加すればよさそうなものですが。そして、Activityが一時停止または停止したら、リスナーとしてのActivityを削除します。実際にそんなことができるのでしょうか?私が考える唯一の方法は、ActivityにParcelableを実装させ、AIDLファイルを作成して、Serviceのリモートインターフェースにそれを渡すことです。しかし、これはやりすぎだと思いますし、ActivityがどのようにwriteToParcel() / readFromParcel()を実装すればいいのか見当がつきません。

もっと簡単で良い方法はないでしょうか?助けてくれてありがとうございます。

EDITです。

後で興味を持った人のために、AIDLでこれを処理するためのGoogleのサンプルコードがsamplesディレクトリにあります。/apis/app/RemoteService.javaにあります。

解決するには?

サービスとのコミュニケーションには、3つの明白な方法があります。

  1. インテントの使用
  2. AIDLを使用する
  3. サービスオブジェクトそのものを使う(シングルトンとして)

あなたの場合、私なら3の選択肢を選びます。サービス自身への静的な参照を作成し、onCreate()でそれを入力します。

void onCreate(Intent i) {
  sInstance = this;
}

静的関数を作る MyService getInstance() を返す、静的な sInstance .

次に Activity.onCreate() サービスを開始し、サービスが実際に開始されるまで非同期で待機し(アクティビティにインテントを送信することで、サービスが準備できたことをアプリに通知させることができます)、そのインスタンスを取得するのです。インスタンスを取得したら、サービスリスナーオブジェクトをサービスに登録すれば、設定完了です。注:アクティビティ内でViewを編集する場合は、UIスレッドで変更する必要があります。 Activity.runOnUiThread() .

最後に、リスナーオブジェクトへの参照を削除する必要があります。 Activity.onPause() そうしないと、アクティビティコンテキストのインスタンスがリークしてしまい、よくありません。

注意: この方法は、アプリケーション/アクティビティ/タスクがサービスにアクセスする唯一のプロセスである場合にのみ有効です。そうでない場合は、オプション 1 か 2 を使用しなければなりません。