June 13, 2012

Broadcast intentを送受信する

Broadcast intentの送受信の使い方です。

Broadcast intentとは、Implicit intent(暗黙的なintent)とほぼ同じものですが、1点だけ大きく異なるところがあります(Implicit intentについては「外部アプリから起動されるアプリを作る」を参照)。それは、Implicit intentが選択された1つのActivityしか受信できないのに対し、Broadcast intentは基本的に全Activityが受信できます。受信するかどうかIntent filterで設定するのは同じです。

ただし、基本的に全Activityと書いたのは、そうでないBroadcast intentもあるからです。Broadcast intentを投げる方法は2通りあり、1つはsendBroadcast()を使います。この場合、全Activityが一斉に(非同期に)受信できます。もう1つの方法はsendOrderedBroadcast()で、これは受信するActivityに優先順位をつけて1つづつ順番に通知していきながら全Activityまで通知していく方法です。この場合、途中でActivityが次に通知するか停止するか選択する権利があり、全Activityが受信できるとは限らない仕様になっています。優先順位はIntent filterのpriorityの値で決まります。同じ値の場合の優先順位は不定です。

このBroadcast intentはシステムも多く発信しており、バッテリーや通信状況、デバイスの接続、などなどさまざまな状況変化を通知しています。そのようなシステムの状態変化を察知するのにも使えます。どんなBroadcast intentがあるかはintentのドキュメントに一覧が記載されています。またアプリ間連携でオリジナルのBroadcast intentを通知することもできます。ただし、名前がかぶらないように通常はaction名にアプリのpackage名を先頭にいれるのが慣例のようです。

上記の方法で送信されたBroadcast intentは、専用のBroadcastReceiverクラスのみ受信することができます。通常のActivityクラスなどでは受信できません。

例)システムが発行する日付のタイムゾーン変化の通知の受信、およびオリジナルのBroadcast intentの発行と受信を行う場合、sendBroadcast()で発行し、BroadcastReceiverクラスを作成し、Intent filterを設定して受信します。

public class SampleAppActivity extends Activity {
    private final static String TAB = "SampleAppActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("jp.myapp.sample.clicked");
                sendBroadcast(intent);
            }
        });
    }
}

public class SampleReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("RECEIVE", "action:" + intent.getAction());
    }
}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.myapp.sample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
        <activity
            android:name="SampleAppActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name="SampleReceiver">
            <intent-filter>
                <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
                <action android:name="jp.myapp.sample.clicked"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

参考:Android Developers:BroadcastReceiver
参考:Android Developers:Intent

No comments:

Post a Comment