Android(安卓)广播接收器(Broadcast Receiver)

广播接收器(Broadcast Receiver)仅响应来自其他应用程序或系统本身的广播消息。这些消息有时称为事件或意图。例如,应用程序还可以启动广播,以让其他应用程序知道一些数据已下载到设备并可供其使用,因此这是广播接收器,它将拦截此通信并启动适当的操作。

要使广播接收器为系统广播意图工作,有以下两个重要步骤:

  • 创建广播接收器。
  • 注册广播接收器

如果您要实现自定义意图,还有一个额外的步骤,那么您必须创建并广播这些意图。


创建广播接收器

广播接收器实现为 BroadcastReceiver 类的子类,并且重写onReceive()方法,在该方法中,每个消息均作为 Intent 对象参数接收。

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

注册广播接收器

应用程序通过在 AndroidManifest.xml 文件中注册广播接收器来侦听特定的广播意图(indent)。考虑一下,我们将为系统生成的事件 ACTION_BOOT_COMPLETED 注册 MyReceiver,一旦 Android 系统完成启动过程,系统就会触发该事件。

  1. <application
  2. android:icon="@drawable/ic_launcher"
  3. android:label="@string/app_name"
  4. android:theme="@style/AppTheme" >
  5. <receiver android:name="MyReceiver">
  6. <intent-filter>
  7. <action android:name="android.intent.action.BOOT_COMPLETED">
  8. </action>
  9. </intent-filter>
  10. </receiver>
  11. </application>

现在,无论何时启动 Android 设备,它都会被广播接收器 MyReceivers 截获,并执行 onReceive() 内的实现逻辑。

有几个系统生成的事件定义为 Intent 类中的最终静态字段。下表列出了一些重要的系统事件。

编号事件常量 & 描述
1

android.intent.action.BATTERY_CHANGED

粘滞广播,包含充电状态、电量和其他有关电池的信息。

2

android.intent.action.BATTERY_LOW

表示设备电池电量不足。

3

android.intent.action.BATTERY_OKAY

表示电池电量低后现在正常。

4

android.intent.action.BOOT_COMPLETED

这在系统完成启动后广播一次。

5

android.intent.action.BUG_REPORT

显示报告 bug 的 activity 活动。

6

android.intent.action.CALL

呼叫数据指定的人。

7

android.intent.action.CALL_BUTTON

用户按下 "呼叫" 按钮,转到拨号器或其他合适的用户界面进行呼叫。

8

android.intent.action.DATE_CHANGED

数据已修改。

9

android.intent.action.REBOOT

重新启动设备。


广播自定义意图(Intents)

如果您希望应用程序本身应生成并发送自定义意图,则必须使用 Activity 类中的 sendBroadcast() 方法来创建并发送这些意图(Indent)。如果您使用 sendStickyBroadcast(Intent) 方法,则该 Intent 是粘性的,这意味着您要发送的 Intent 在广播完成后仍然存在。

  1. public void broadcastIntent(View view) {
  2. Intent intent = new Intent();
  3. intent.setAction("com.cankaoshouce.CUSTOM_INTENT");
  4. sendBroadcast(intent);
  5. }

这个意图 com.cankaoshouce.CUSTOM_INTENT 也可以通过类似于我们重新注册系统生成的意图的方式进行注册。

  1. <application
  2. android:icon="@drawable/ic_launcher"
  3. android:label="@string/app_name"
  4. android:theme="@style/AppTheme" >
  5. <receiver android:name="MyReceiver">
  6. <intent-filter>
  7. <action android:name="com.cankaoshouce.CUSTOM_INTENT">
  8. </action>
  9. </intent-filter>
  10. </receiver>
  11. </application>

实例

下面的实例将解释如何创建广播接收器以拦截自定义意图。一旦熟悉了自定义意图,就可以对应用程序进行编程,以拦截系统生成的意图。因此,让我们按照以下步骤修改我们在 Hello World 实例 一章中创建的 Android 应用程序:

步骤描述
1您将使用 Android Studio 创建一个 Android 应用程序,并将其命名为 HelloWorld,位于 com.example.cankaoshouce.myapplication 包下。
2修改主 activity 文件 MainActivity.java 来添加 broadcastIntent() 方法。
3在包 com.example.cankaoshouce.myapplication 下创建一个新的 java 文件 MyReceiver.java 来定义广播接收器。
4应用程序可以处理一个或多个自定义和系统意图,而没有任何限制。您要拦截的每个意图都必须使用 <receiver … /> 标记注册到您的 AndroidManifest.xml 文件中
5修改 res/layout/activity_main.xml 文件的默认内容,来包含一个用于广播意图的按钮。
6无需修改字符串文件,Android studio 会处理字符串 xml 文件。
7运行应用程序以启动 Android 模拟器,并验证应用程序中所做更改的结果。

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

  1. package com.example.cankaoshouce.myapplication;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. public class MainActivity extends Activity {
  7. /** Called when the activity is first created. */
  8. @Override
  9. public void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12. }
  13. // broadcast a custom intent.
  14. public void broadcastIntent(View view){
  15. Intent intent = new Intent();
  16. intent.setAction("com.cankaoshouce.CUSTOM_INTENT"); sendBroadcast(intent);
  17. }
  18. }

MyReceiver.java 的内容如下:

  1. package com.example.cankaoshouce.myapplication;
  2. import android.content.BroadcastReceiver;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.widget.Toast;
  6. /**
  7. * Created by cankaoshouce on 10/18/2022.
  8. */
  9. public class MyReceiver extends BroadcastReceiver{
  10. @Override
  11. public void onReceive(Context context, Intent intent) {
  12. Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
  13. }
  14. }

以下是 AndroidManifest.xml 文件的修改内容。这里我们添加了 <receiver…/> 标签来包含我们的服务:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.cankaoshouce.myapplication">
  4. <application
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:supportsRtl="true"
  9. android:theme="@style/AppTheme">
  10. <activity android:name=".MainActivity">
  11. <intent-filter>
  12. <action android:name="android.intent.action.MAIN" />
  13. <category android:name="android.intent.category.LAUNCHER" />
  14. </intent-filter>
  15. </activity>
  16. <receiver android:name="MyReceiver">
  17. <intent-filter>
  18. <action android:name="com.cankaoshouce.CUSTOM_INTENT">
  19. </action>
  20. </intent-filter>
  21. </receiver>
  22. </application>
  23. </manifest>

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

  1. <RelativeLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. android:paddingBottom="@dimen/activity_vertical_margin"
  10. tools:context=".MainActivity">
  11. <TextView
  12. android:id="@+id/textView1"
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:text="Example of Broadcast"
  16. android:layout_alignParentTop="true"
  17. android:layout_centerHorizontal="true"
  18. android:textSize="30dp" />
  19. <TextView
  20. android:id="@+id/textView2"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="参考手册 "
  24. android:textColor="#ff87ff09"
  25. android:textSize="30dp"
  26. android:layout_above="@+id/imageButton"
  27. android:layout_centerHorizontal="true"
  28. android:layout_marginBottom="40dp" />
  29. <ImageButton
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content"
  32. android:id="@+id/imageButton"
  33. android:src="@drawable/abc"
  34. android:layout_centerVertical="true"
  35. android:layout_centerHorizontal="true" />
  36. <Button
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:id="@+id/button2"
  40. android:text="广播意图"
  41. android:onClick="broadcastIntent"
  42. android:layout_below="@+id/imageButton"
  43. android:layout_centerHorizontal="true" />
  44. </RelativeLayout>

让我们尝试运行我们修改过的 Hello World!我们刚刚修改的应用程序。我假设您在进行环境设置时创建了 AVD。要从 Android studio 运行应用程序,请打开项目的活动文件之一,然后从工具栏中单击 Eclipse Run Icon 图标。Android Studio 在您的 AVD 上安装应用程序并启动它,如果您的设置和应用程序一切正常,它将显示模拟器窗口。

现在启动广播接收器,让我们单击 “广播意图” 按钮,这将启动广播接收器,一条广播消息将出现在模拟器的底部。

您可以尝试实现其他广播接收器来拦截系统生成的意图,如系统启动、更改日期、电池电量不足等。