Android Broadcast Receivers

Широковещательные приемники используются для ответа на широковещательные сообщения, отправляемые другими приложениями или системой. Эти сообщения иногда называют событиями или интентами. Например, приложение может инициировать широковещательную рассылку, чтобы сообщить другим приложениям, что некоторые данные были загружены на устройство и доступны им. Таким образом, широковещательные приемники могут определять соответствующие действия для перехвата этих сообщений.

Ниже приведены два важных шага, необходимых для того, чтобы широковещательные интенты системы работали с широковещательными приемниками.

  • Создание широковещательного приемника
  • Регистрация широковещательного приемника

Есть еще один дополнительный шаг. Чтобы реализовать пользовательские интенты, вы должны создать и широковещательно отправить эти интенты.


Создание широковещательного приемника

Широковещательный приемник необходимо реализовать как подкласс класса BroadcastReceiver и переопределить метод onReceive() для получения сообщений, которые принимают объект Intent в качестве параметра.

public class MyReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
      Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
   }
}

Регистрация широковещательного приемника

Приложение регистрирует широковещательный приемник в AndroidManifest.xml для прослушивания определенных широковещательных интентов. Предположим, мы собираемся зарегистрировать MyReceiver для прослушивания события ACTION_BOOT_COMPLETED, генерируемого системой. Это событие отправляется по завершении процесса загрузки системы Android.

广播接收器(Broadcast Receivers)

<application
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >
   <receiver android:name="MyReceiver">

      <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED">
         </action>
      </intent-filter>

   </receiver>
</application>

Теперь, всякий раз при загрузке Android-устройства, событие будет перехвачено широковещательным приёмником MyReceiver, и будет выполнена логика, реализованная в onReceive().

В классе Intent определено множество системных событий, заданных в виде статических констант. В следующей таблице перечислены важные системные события.

Константа события Описание
android.intent.action.BATTERY_CHANGED Закреплённое широковещательное сообщение, содержащее состояние зарядки аккумулятора, уровень заряда и другую информацию.
android.intent.action.BATTERY_LOW Указывает на низкий уровень заряда аккумулятора на устройстве.
android.intent.action.BATTERY_OKAY Указывает, что аккумулятор после низкого уровня заряда теперь в норме.
android.intent.action.BOOT_COMPLETED Широковещательное сообщение, отправляемое один раз после завершения загрузки системы.
android.intent.action.BUG_REPORT Отображает активность для сообщения об ошибке.
android.intent.action.CALL Звонит лицу, указанному в данных вызова.
android.intent.action.CALL_BUTTON Пользователь нажимает кнопку "Вызов", чтобы открыть средство набора номера или другой подходящий интерфейс для набора.
android.intent.action.DATE_CHANGED Дата изменилась.
android.intent.action.REBOOT Устройство было перезагружено.

Широковещательная рассылка пользовательских интентов

Если вы хотите генерировать и отправлять пользовательские интенты в своём приложении, вам нужно создавать и отправлять эти интенты через sendBroadcast() в классе вашей активности. Если вы используете метод sendStickyBroadcast(Intent), интент является sticky, что означает, что отправленный вами интент остаётся после завершения широковещательной рассылки.

public void broadcastIntent(View view)
{
   Intent intent = new Intent();
   intent.setAction("com.example.CUSTOM_INTENT");
   sendBroadcast(intent);
}

Интент с com.example.CUSTOM_INTENT можно зарегистрировать так же, как мы ранее регистрировали интенты, сгенерированные системой.

<application
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >
   <receiver android:name="MyReceiver">

      <intent-filter>
         <action android:name="com.example.CUSTOM_INTENT">
         </action>
      </intent-filter>

   </receiver>
</application>

Пример

В этом примере объясняется, как создать широковещательный приёмник для перехвата пользовательского intent. Освоив пользовательские intent, вы сможете запрограммировать своё приложение на перехват системных intent. Выполним приведённые ниже шаги, чтобы изменить приложение Android, созданное в главе с примером Hello World.

Шаг Описание
1 Используйте Android Studio, чтобы создать приложение Android, назовите его broadcastreceiver и разместите его в пакете com.example.broadcastreceiver, как в главе с примером Hello World.
2 Измените файл основной активности MainActivity.java, добавив метод broadcastIntent().
3 Создайте новый файл Java с именем MyReceiver.java в пакете com.example.broadcastreceiver, чтобы определить широковещательный приёмник.
4 Приложение может обрабатывать один или несколько пользовательских или системных intent без каких-либо ограничений. Каждый intent, который вы хотите перехватывать, необходимо зарегистрировать в AndroidManifest.xml с помощью тега <receiver.../>.
5 Измените содержимое файла res/layout/activity_main.xml по умолчанию, добавив кнопку для широковещательной отправки intent.
6 Нет необходимости изменять файл строковых ресурсов; Android Studio позаботится о файле string.xml.
7 Запустите эмулятор Android, чтобы запустить приложение и проверить результаты внесённых в приложение изменений.

Ниже приведено содержимое изменённого файла основной активности src/com.example.broadcastreceiver/MainActivity.java. Этот файл содержит каждый из базовых методов жизненного цикла. Мы добавили метод broadcastIntent() для широковещательной отправки пользовательских событий.

package com.example.broadcastreceiver;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.content.Intent;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    // 广播自定义意图
    public void broadcastIntent(View view){
        Intent intent = new Intent();
        intent.setAction("cn.programmer.CUSTOM_INTENT");
        sendBroadcast(intent);
    }
}

Ниже приведено содержимое src/com.example.broadcastreceiver/MyReceiver.java:

package com.example.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "检测到意图。", Toast.LENGTH_LONG).show();
    }
}

Затем измените файл AndroidManifest.xml. Здесь мы включаем наш широковещательный приёмник, добавляя тег <receiver.../>:

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="22" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

        </activity>

        <receiver android:name="MyReceiver">

            <intent-filter>
                <action android:name="cn.programmer.CUSTOM_INTENT">
                </action>
            </intent-filter>

        </receiver>

    </application>

</manifest>

Ниже приведено содержимое файла res/layout/activity_main.xml, содержащего кнопку для широковещательной отправки пользовательского intent.

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="广播实例"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textSize="30dp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="www.example.com"
        android:textColor="#ff87ff09"
        android:textSize="30dp"
        android:layout_above="@+id/imageButton"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="40dp" />

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton"
        android:src="@drawable/ic_launcher.html"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:text="广播意图"
        android:onClick="broadcastIntent"
        android:layout_below="@+id/imageButton"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Ниже приведено содержимое файла res/values/strings.xml, в котором определены две новые константы.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Android Broadcast Receiver</string>
    <string name="action_settings">Settings</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">Main Activity</string>

</resources>

Давайте запустим приложение Hello World!, которое мы только что изменили. Предполагаю, что вы уже создали AVD при настройке окружения. Откройте файл activity в вашем проекте и нажмите图片значок на панели инструментов, чтобы запустить приложение в Android Studio. Android Studio устанавливает приложение на AVD и запускает его. Если всё пройдёт гладко, в окне эмулятора отобразится следующее:

图片

Теперь нажмите кнопку "Broadcast Intent", чтобы отправить широковещательный intent. Это отправит наш пользовательский intent "cn.programmer.CUSTOM_INTENT", который будет перехвачен нашим зарегистрированным широковещательным приёмником MyReceiver, и тот выполнит реализованную нами логику. В нижней части эмулятора появится всплывающее сообщение, как показано ниже:

图片

Вы можете попробовать реализовать другие широковещательные приёмники для перехвата intent-ов, генерируемых системой, таких как загрузка системы, изменение даты, низкий заряд батареи и так далее.

Другие расширения