Android (Kotlin) でブロードキャスト送受信の仕方を理解する


きっかけ

最近、Android 開発を仕事で行っていますが、複数のアプリ間連携の方法を今まで知りませんでした。
最近知ったのですが、IntentBroadcastReceiverを使用することで簡単にアプリ間連携が可能でした。

しかし、まったくの初心者であった自分にとっては???でした。。
そこで今回は 2 つのアプリを連携させるIntentの使い方について学ぶことができたので、共有します。

環境

  • Android Studio 3.6.1
  • Android 7.0 以降

概要

1 つの Android 端末に 2 つのアプリケーションをインストールし、その 2 つのアプリ間の連携方法について記述します。
今回作成するアプリは以下になります。

IntentBroadcast アプリ

  • Intentを Android 端末アプリケーション内の全てのアプリにブロードキャストするアプリケーション

IntentReceiver アプリ

  • ブロードキャストされたIntentを受信するアプリケーション

1. IntentBroadcast アプリについて

Activity 画面にボタンを配置し、そのボタンをタップすることでIntentを送信します。
ブロードキャストの方法は、以下のようにIntentインスタンスを作成し、sendBroadcast(intent)を実行することで可能です。

MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // ボタン1配置
        button1.setOnClickListener {
            // インテントをブロードキャスト
            val intent = Intent("com.example.broadcast.MY_NOTIFICATION1")
            intent.putExtra("data", "Notice me senpai!")
            sendBroadcast(intent)
        }

        // ボタン2配置
        button2.setOnClickListener {
            // インテントをブロードキャスト
            val intent = Intent("com.example.broadcast.MY_NOTIFICATION2")
            intent.putExtra("data", "Hello, world!")
            sendBroadcast(intent)
        }
    }
}

ここで、Intentのインスタンス作成時に以下のように Action 文字列をセットしています。
Intentを受信するレシーバはこのcom.example.broadcast.MY_NOTIFICATION1の部分を確認し、受け取るべき情報なのかを判断します。

そのため一意であればどんな文字列でも構いませんが、作法として「パッケージ名 + 任意の文字列」とするのがベターです。
(Android 端末内のアプリケーションのパッケージ名は基本的に一意であるためです。)

また、IntentputExtra()を利用することで情報を追加登録することができます。
今回はdataという名前でそれぞれ文字列をセットしました。



ちなみに以下のactivity_main.xmlstrings.xmlは画面にボタンを設置するために記述しているだけで、ブロードキャスト処理には関係ありません。
上記のソースを動かす際のサンプル用として参考してください。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="50dp"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button1" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button2" />
</LinearLayout>
strings.xml
<resources>
    <string name="app_name">IntentBroadcast</string>
    <string name="button1">Button1</string>
    <string name="button2">Button2</string>
</resources>

2. IntentReceiver アプリについて

こちらは Android 端末内にブロードキャストされているIntentを受信します。
受信の方法はまず、BroadcastReceiverクラスを継承した、ブロードキャストを実際に受信するクラス(MyBroadcastReceiverクラス)を作成します。

そしてメイン画面に、先ほど作成したMyBroadcastReceiverクラスを利用するレシーバを準備することでIntent受信が可能となります。

MyBroadcastReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast

class MyBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        // インテントに登録されている、名前"data"に対応する文字列をトーストで表示する
        Toast.makeText(context, intent?.getStringExtra("data"), Toast.LENGTH_SHORT).show()
    }
}
MainActivity.kt
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // BroadcastReceiverを継承したクラス(MyBroadcastReceiver)を指定する
        // IntentFilterは何を呼び出すかを振り分けるもの
        // 2020/03/20: links_2_3_4 さん指摘反映
        // 画面回転時にメモリリークに関する警告表示を阻止
        this.applicationContext.registerReceiver(
            MyBroadcastReceiver(),
            IntentFilter("com.example.broadcast.MY_NOTIFICATION1")
        )
        this.applicationContext.registerReceiver(
            MyBroadcastReceiver(),
            IntentFilter("com.example.broadcast.MY_NOTIFICATION2")
        )
    }
}

ここでMainActivity.ktでは、Intentの Action 文字列によってどのブロードキャストレシーバクラスを利用するかを設定しています。
(今回は同じブロードキャストレシーバクラスMyBroadcastReceiver()を設定しています。)

そしてIntentの Action 文字列(com.example.broadcast.MY_NOTIFICATION1)が、IntentFilter()内でで記述した文字列と同じであれば、設定したブロードキャストクラス内の処理が実行されます。

ブロードキャストレシーバクラスMyBroadcastReceiver.ktでは、Intentに登録された名前dataの文字列をトーストで表示するようにしました。

挙動確認

  1. IntentBroadcast アプリと IntentReceiver アプリを Android 端末にインストールします。
  2. IntentReceiver アプリを起動し、ホームボタンを選択するなどしてバックグラウンドに移動させます。
  3. IntentBroadcast アプリを起動し、画面上に設置したボタンをタップします。

うまくブロードキャスト送信・受信ができればIntentに登録したdataの文字列がトースト表示されます。

これで、IntentBroadcast アプリで操作した情報が IntentReceiver アプリに受け渡され、2 つのアプリ間連携ができました。

最後に

今回は、1 つのアプリケーションでIntentをブロードキャストを行い、もう 1 つのアプリケーションでIntentを受け取ってトースト表示する仕組みを紹介しました。
本記事ではとても単純なケースを紹介しましたが、このIntentを使えば、複数の Android アプリケーションでの連携が可能になります。
今後余裕があれば、このIntentのやり取りを利用した他のサンプルも実装・紹介できたらなと思います。

最後まで閲覧いただき、ありがとうございました。