Android 简明教程

Android - Broadcast Receivers

以下两个步骤非常重要,可以使 BroadcastReceiver 处理系统广播的意图 −

There are following two important steps to make BroadcastReceiver works for the system broadcasted intents −

  1. Creating the Broadcast Receiver.

  2. Registering Broadcast Receiver

如果您要实现自定义意图,则还需要一个附加步骤,即必须创建并广播这些意图。

There is one additional steps in case you are going to implement your custom intents then you will have to create and broadcast those intents.

Creating the Broadcast Receiver

广播接收器将作为 BroadcastReceiver 类的子类实现,并覆盖 onReceive() 方法,其中每个消息都接收一个 Intent 对象参数。

A broadcast receiver is implemented as a subclass of BroadcastReceiver class and overriding the onReceive() method where each message is received as a Intent object parameter.

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

Registering Broadcast Receiver

应用程序通过在 AndroidManifest.xml 文件中注册广播接收器来侦听特定广播意图。假设我们要为 Android 系统已完成启动过程后系统触发的系统生成事件 ACTION_BOOT_COMPLETED 注册 MyReceiver。

An application listens for specific broadcast intents by registering a broadcast receiver in AndroidManifest.xml file. Consider we are going to register MyReceiver for system generated event ACTION_BOOT_COMPLETED which is fired by the system once the Android system has completed the boot process.

broadcast
<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() 中实现的逻辑。

Now whenever your Android device gets booted, it will be intercepted by BroadcastReceiver MyReceiver and implemented logic inside onReceive() will be executed.

Intent 类中,有几个以 final static 域定义的系统生成事件。下表列出了几个重要的系统事件。

There are several system generated events defined as final static fields in the Intent class. The following table lists a few important system events.

Sr.No

Event Constant & Description

1

android.intent.action.BATTERY_CHANGED Sticky broadcast containing the charging state, level, and other information about the battery.

2

android.intent.action.BATTERY_LOW Indicates low battery condition on the device.

3

android.intent.action.BATTERY_OKAY Indicates the battery is now okay after being low.

4

android.intent.action.BOOT_COMPLETED This is broadcast once, after the system has finished booting.

5

android.intent.action.BUG_REPORT Show activity for reporting a bug.

6

android.intent.action.CALL Perform a call to someone specified by the data.

7

android.intent.action.CALL_BUTTON The user pressed the "call" button to go to the dialer or other appropriate UI for placing a call.

8

android.intent.action.DATE_CHANGED The date has changed.

9

android.intent.action.REBOOT Have the device reboot.

Broadcasting Custom Intents

如果您希望应用程序自身生成并发送自定义事件,则必须在活动类中使用 sendBroadcast() 方法创建并发送这些事件。如果您使用 sendStickyBroadcast(Intent) 方法,则 sticky 意图即可确保发送的意图在广播完成后仍存在。

If you want your application itself should generate and send custom intents then you will have to create and send those intents by using the sendBroadcast() method inside your activity class. If you use the sendStickyBroadcast(Intent) method, the Intent is sticky, meaning the Intent you are sending stays around after the broadcast is complete.

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

此意图 com.tutorialspoint.CUSTOM_INTENT 也可按与注册系统生成意图类似的方式进行注册。

This intent com.tutorialspoint.CUSTOM_INTENT can also be registered in similar way as we have regsitered system generated 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.tutorialspoint.CUSTOM_INTENT">
         </action>
      </intent-filter>

   </receiver>
</application>

Example

本例将说明如何创建 BroadcastReceiver 以拦截自定义意图。一旦熟悉了自定义意图,您便可对应用程序进行编程以拦截系统生成的意图。因此,让我们按照以下步骤修改在 Hello World Example 章节中创建的 Android 应用程序 −

This example will explain you how to create BroadcastReceiver to intercept custom intent. Once you are familiar with custom intent, then you can program your application to intercept system generated intents. So let’s follow the following steps to modify the Android application we created in Hello World Example chapter −

Step

Description

1

You will use Android studio to create an Android application and name it as My Application under a package com.example.tutorialspoint7.myapplication as explained in the Hello World Example chapter.

2

Modify main activity file MainActivity.java to add broadcastIntent() method.

3

Create a new java file called MyReceiver.java under the package com.example.tutorialspoint7.myapplication to define a BroadcastReceiver.

4

An application can handle one or more custom and system intents without any restrictions. Every intent you want to intercept must be registered in your AndroidManifest.xml file using <receiver…​/> tag

5

Modify the default content of res/layout/activity_main.xml file to include a button to broadcast intent.

6

No need to modify the string file, Android studio take care of string.xml file.

7

Run the application to launch Android emulator and verify the result of the changes done in the application.

以下是已修改的主活动文件 MainActivity.java 的内容。该文件可以包含每个基本生命周期方法。我们已添加了 broadcastIntent() 方法来广播自定义意图。

Following is the content of the modified main activity file MainActivity.java. This file can include each of the fundamental life cycle methods. We have added broadcastIntent() method to broadcast a custom intent.

package com.example.tutorialspoint7.myapplication;

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

public class MainActivity extends Activity {

   /** Called when the activity is first created. */
   @Override

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


   // broadcast a custom intent.

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

以下是 MyReceiver.java 的内容:

Following is the content of MyReceiver.java:

package com.example.tutorialspoint7.myapplication;

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

/**
 * Created by TutorialsPoint7 on 8/23/2016.
 */
public class MyReceiver extends BroadcastReceiver{
   @Override
   public void onReceive(Context context, Intent intent) {
      Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
   }
}

以下是已修改的 AndroidManifest.xml 文件的内容。此处我们添加了 <receiver…​/> 标记以包含我们的服务:

Following will the modified content of AndroidManifest.xml file. Here we have added <receiver…​/> tag to include our service:

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

   <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">

      <activity android:name=".MainActivity">
         <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="com.tutorialspoint.CUSTOM_INTENT">
            </action>
         </intent-filter>

      </receiver>
   </application>

</manifest>

以下是 res/layout/activity_main.xml 文件的内容,其中包含用于广播我们自定义意图的按钮 −

Following will be the content of res/layout/activity_main.xml file to include a button to broadcast our custom 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="Example of Broadcast"
      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="Tutorials point "
      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/abc"
      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="Broadcast Intent"
      android:onClick="broadcastIntent"
      android:layout_below="@+id/imageButton"
      android:layout_centerHorizontal="true" />

</RelativeLayout>

让我们尝试运行刚刚修改的 Hello World! 应用程序。我假设你在执行环境设置时已创建了 AVD 。要从 Android 工作室运行该应用,打开项目的其中一个活动文件并单击工具栏中的运行图标。Android 工作室会在 AVD 上安装该应用并启动该应用,如果设置和应用程序一切正常,便会显示以下仿真器窗口 −

Let’s try to run our modified Hello World! application we just modified. I assume you had created your AVD while doing environment set-up. To run the app from Android studio, open one of your project’s activity files and click Run icon from the tool bar. Android Studio installs the app on your AVD and starts it and if everything is fine with your set-up and application, it will display following Emulator window −

broadcast1

现在,若要广播我们的自定义意图,请单击 Broadcast Intent 按钮,这会广播我们的自定义意图“com.tutorialspoint.CUSTOM_INTENT”,我们的已注册 BroadcastReceiver(即 MyReceiver)会拦截此意图,并根据我们实现的逻辑,会在仿真器的底部显示一个吐司,如下所示 −

Now to broadcast our custom intent, let’s click on Broadcast Intent button, this will broadcast our custom intent "com.tutorialspoint.CUSTOM_INTENT" which will be intercepted by our registered BroadcastReceiver i.e. MyReceiver and as per our implemented logic a toast will appear on the bottom of the the simulator as follows −

broadcast2

你可以尝试实现其他 BroadcastReceiver 以拦截系统生成的意图,如系统启动、日期更改、电量不足等。

You can try implementing other BroadcastReceiver to intercept system generated intents like system boot up, date changed, low battery etc.