谨以文章记录学习历程,如有错误还请指明。

前言

我们上学时都有过这样的经历,当我们在火车站列车候车室中等待时,每当有某次列车开始检票或者进站上车时,就会播放通知来告知在候车室等待的人们该消息。

为了便于进行系统级别的消息通知,Android引入了一套类似的广播机制,然而比上述情景要灵活得多。此文将对Android广播机制的方方面面做出详尽的介绍。


Android广播机制简介

前面我们提到,Android的广播机制更加的灵活,这是因为Android允许每个应用只对自己感兴趣的广播进行注册,这样该程序就只会收到自己所关心的广播内容。
Android广播分为两个方面:广播发送者广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者广播接收器)。

应用场景

同一应用具有多个进程的不同组件之间的消息通信

  • 不同应用间的组件之间的消息通信
  • 与Android系统在特定情况下的通信
  • 如:系统开机,网络变化等

以上只说明适合广播机制的应用场景,还有一些场景理论上可以使用,但是实际开发没有人这么做:

  • 同一应用内同一组件的消息通信:显然扩展变量的作用域、接口回调、Handler-Message等方式都能更简单的实现。

  • 同一应用内的不同组件之间的消息通信(单个进程):对于简单的的情况,依靠接口的回调方式就可解决;而较为复杂的情况,更推荐直接使用EventBus等。

实现原理

设计模式与模型

Android中的广播使用了观察者模式,模型为 基于消息的发布/订阅事件模型

从设计模式上讲,广播的发送者和接收者极大程度的解耦,使得系统方便集成,容易扩展

模型成员:

  • 消息发布者(广播发布者)
  • 消息订阅者(广播接收者)
  • 消息中心(AMS,Activity Manager Service,一个Android系统中极其重要!的成分,以后我们会详细讲解)

此处我们扩展一下,观察者模式和发布订阅模式的关系

  • 发布订阅模式属于广义上的观察者模式
    前者时最常用的一种观察者模式的实现,且从解耦重用角度上看更优于典型的观察者模式

  • 发布订阅模式加入消息中心,实现发布者和订阅者的解耦

    • 在观察者模式中,观察者需要直接订阅目标事件,在目标发出内容改变的事件后,直接接收事件并作出响应。
    • 在发布订阅模式中,多了一个消息中心,一方面从发布者接收事件,另一方面向订阅者发布事件,订阅者需要从消息中心订阅事件。以此避免发布者和订阅者之间产生依赖关系。

实现流程

  1. 广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
  2. 广播发送者通过binder机制向AMS发送广播;
  3. AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver
  4. AMS将广播发送到上述符合条件的BroadcastReceiver相应的消息循环队列中
  5. BroadcastReceiver通过消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。

BroadcastReceiver

自定义BroadcastReceiver

  • 继承基类BroadcaseReceiver
  • 实现抽象方法onReceive(context, intent)

    • 收到广播后,会自动回调onReceive(..)方法
    • 通常,onReceive(..)方法会涉及到与其他组件的交互,如发送Notification,启动service
    • 默认情况,BroadcaseReceiver运行在UI线程,因此,onReceive(..)方法不能执行耗时操作,否则ANR
  • 简单的自定义Demo:
    MyBroadcastReceiver.java

//继承BroadcastReceiver基类public class MyBroadcastReceiver extends BroadcastReceiver {    private static final String TAG = "MyBroadcastReceiver";    @Override    public void onReceive(Context context, Intent intent) {        StringBuilder sb = new StringBuilder();        sb.append("Action: " + intent.getAction() + "\n");        sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");        String log = sb.toString();        Log.d(TAG, log);        Toast.makeText(context, log, Toast.LENGTH_LONG).show();    }}

BroadcastReceiver注册类型

1. 静态注册

  • AndroidManifest.xml文件中通过进行注册
  • 规则及实例说明:
 //BroadcastReceiver子类的类名    android:name="string"    //是否使用该BroadcastReceiver    android:enabled=["true" | "false"]    //此broadcastReceiver能否接收其他App的发出的广播    //其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false    android:exported=["true" | "false"]    android:icon="drawable resource"    android:label="string resource"    //具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收    android:permission="string"    //broadcastReceiver运行所处的进程。    //默认为app的进程,可以指定独立的进程    //Android四大基本组件都可以通过此属性指定自己的独立进程    android:process="string">    //指定此广播接收器将用于接收特定的广播类型    //本例中给出的时系统开机后自身发出的广播    filter>        "android.intent.action.BOOT_COMPLETED"/>    filter>

以上述静态方法注册的MyBroadcastReceiver,在app首次启动时,系统或自动实例化MyBroadcastReceiver,并注册到系统中。

2. 动态注册

  • 在代码中调用Context.registerReceiver()
  • 典型写法示例如下:
public class MainActivity extends AppCompatActivity {    public static final String BROADCAST_ACTION = "com.example.whd_alive";    private BroadcastReceiver mBroadcastReceiver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //实例化MyBroadcastReceiver         mBroadcastReceiver = new MyBroadcastReceiver();        //实例化IntentFilter        IntentFilter intentFilter = new IntentFilter();        //设置接收广播的类型        intentFilter.addAction(BROADCAST_ACTION);        //动态注册        registerReceiver(mBroadcastReceiver, intentFilter);    }    //销毁广播    //当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中    //当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(mBroadcastReceiver);    }}

注:Android中所有与观察者模式有关的设计中,一旦涉及到register,必定在相应的时机需要unregister。因此,上例在onDestroy()回调需要unregisterReceiver(mBroadcastReceiver)

广播发送及广播类型

广播发送

  • 广播 这一实体本身以 intent 表示
  • 广播的定义 = 相应广播intent的定义
  • 广播的发送:通过广播发送者将此intent发送出去,根据不同类型的广播调用相对应的send方法

广播的类型

主要分为一下四类:

  1. Normal Broadcast(普通广播):通常调用sendBroadcast(Intent)(Intent, String)方法发送
  2. System Broadcast(系统广播):发生各种事件时,系统自动发送
  3. Ordered Broadcast(有序广播):调用sendOrderedBroadcast(Intent, String)方法发送
  4. Local Broadcast(本地广播):调用LocalBroadcastManager.sendBroadcast(intent)方法发送
  5. Sticky Broadcast(粘性广播):已弃用(API 21)

1. Normal Broadcast(普通广播)

开发者自定义的intent,以Context.sendBroadcast()Context.sendBroadcastAsUser()等方法发送该intent

  • 发送示例如下:
        Intent intent = new Intent();        intent.setAction(BROADCAST_ACTION);        //最普通的发送方式        sendBroadcast(intent);        //附带权限的发送方式,声明此权限的BroadcastReceiver才能接收此广播        sendBroadcast(intent,RECEIVER_PREMISSION);        //以下两种不常见,是因为只有预装在系统映像中的程序才能使用,否则无法使用        //指明接收人的发送方式        sendBroadcastAsUser(intent,USER_HANDLER);        //指明接收人以及对应权限的发送方式        sendBroadcastAsUser(intent,USER_HANDLER,RECEIVER_PREMISSION);
  • 若被注册了的BroadCastReceiver注册的intentFilteraction与上述匹配,则会接收此广播,且顺序是无序的。如果发送时有相应的权限要求,则BroadCastReceiver只有拥有相应的权限才能接受。
<receiver    android:name=".MyBroadcastReceiver"    android:permission="RECEIVER_PREMISSION">    <intent-filter>        <action android:name="BROADCAST_ACTION"/>    intent-filter>receiver>

2. System Broadcast(系统广播)

文末提供详细系统广播清单,不包含使用说明(位于SDK下boradcast_action.txt ),请自行查找Google官方文档

Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。

3. Ordered Broadcast(有序广播))

  • 发送出去的广播被BroadcastReceiver按照先后循序接收。

    有序广播的有序广播中的“有序”是针对广播接收者而言的

  • 发送方式:

    • 定义过程与普通广播一样,调用sendOrderedBroadcast(),同样也有对应的sendOrderedBroadcastAsUser()方法,只不过同样针对于预装在系统映像的应用。
  • 特点

    1. 按顺序接收
    2. 允许优先级高的BroadcastReceiver截断广播。
    3. 允许优先级高的BroadcastReceiver修改广播
  • 接受顺序

    • priority值不同:由大到小排序
    • priority值相同:动态注册优于静态注册

4. Local Broadcast(本地广播)

  • 可以理解成一种局部广播的形式,广播的发送者和接收者都同属于一个App
  • 相比于全局广播,本地广播优势体现在:

    • 安全性更高;
    • 更加高效。
  • 引入原因:

    • 其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;
    • 其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。
  • 解决方案

    1. 全局广播限制为局部广播(本质仍为一个全局广播)
    2. 使用本地广播
  • 方案1的具体实现:

    • 对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;
    • 在广播发送和接收时,都增加上相应的permission,用于权限验证;
    • 发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
  • 方案2的具体实现:
    使用封装好的LocalBroadcastManager类。
    使用方式上与通常的全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将主调context变成了LocalBroadcastManager的单一实例。

对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(静态注册或其他方式动态注册的ContextReceiver是接收不到的)

代码示例如下:

//实例化MyBroadcastReceivermBroadcastReceiver = new MyBroadcastReceiver();//实例化IntentFilterIntentFilter intentFilter = new IntentFilter();//得到LocalBroadcastManager实例LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);//设置接收广播的类型intentFilter.addAction(BROADCAST_ACTION);//动态注册localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);//取消注册localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

不同注册方式的广播接收器回调onReceive(context, intent)中的context具体类型

  • 静态注册(全局+本地):
    回调onReceive(context, intent)中的context具体指的是ReceiverRestrictedContext
  • 全局动态注册:
    回调onReceive(context, intent)中的context具体指的是Activity Context
  • LocalBroadcastManager动态注册
    回调onReceive(context, intent)中的context具体指的是Application Context

Android 7.0以后的新特性

以上我们讨论了老生常谈的内容,下面我们谈一谈Android 7.0以后的新变化

  • Android 7.0起,系统不再发送以下系统广播:

    • ACTION_NEW_PICTURE
    • ACTION_NEW_VIDEO
  • 针对Android 7.0 (API级别24)和更高版本的应用程序必须通过registerReceiver()注册以下广播。在AndroidManifest中声明起作用。

    • CONNECTIVITY_ACTION
  • Android 8.0起,应用无法在Manifest中注册大部分隐式系统广播(即,并非专门针对此应用的广播),此意也是在于降低随Android同时运行的应用增多,发生性能变差的几率。


出于安全考虑的广播使用最佳实践

  • 如不需要向应用程序之外的组件发送广播,则可以使用支持库Support LibraryLocalBroadcastManager发送和接收本地广播。

  • 如果许多应用程序清单中注册接收相同的广播,它会导致系统启动大量的应用程序,从而对设备性能和用户体验产生重大影响。为了避免这种情况,请使用动态注册而不是Manifest声明。有时,Android系统本身会强制使用上下文注册的接收器。例如,CONNECTIVITY_ACTION广播只允许动态注册。

  • onReceive(Context, Intent)运行在UI线程,不要进行耗时操作

    • 如耗时操作必不可少,生成子线程。
  • 不要使用隐含的意图传播敏感信息。这些信息可以被任何注册的应用程序读取。

    • 解决方案 : permission / setPackage(String) / LocalBroadcastManager.
  • 当注册一个BroadcastReceiver,任何应用程序都可以发送潜在的恶意广播到你的应用的BroadcastReceiver

    • 解决方案 : permission / android:exported = "false" / LocalBroadcastManager.
  • 广播操作的命名空间是全局的。确保操作名称和其他字符串都是在您自己的名称空间中编写的,否则您可能会无意中与其他应用程序发生冲突。

  • 不要从BroadcastReceiver开始活动,这么做会导致用户体验很差,特别是如果有不止一个BroadcastReceiver。相反,考虑使用Notification


附录

Android 系统广播清单

android.accounts.LOGIN_ACCOUNTS_CHANGED
android.accounts.action.ACCOUNT_REMOVED
android.app.action.ACTION_PASSWORD_CHANGED
android.app.action.ACTION_PASSWORD_EXPIRING
android.app.action.ACTION_PASSWORD_FAILED
android.app.action.ACTION_PASSWORD_SUCCEEDED
android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED
android.app.action.APP_BLOCK_STATE_CHANGED
android.app.action.DEVICE_ADMIN_DISABLED
android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED
android.app.action.DEVICE_ADMIN_ENABLED
android.app.action.DEVICE_OWNER_CHANGED
android.app.action.INTERRUPTION_FILTER_CHANGED
android.app.action.LOCK_TASK_ENTERING
android.app.action.LOCK_TASK_EXITING
android.app.action.NEXT_ALARM_CLOCK_CHANGED
android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED
android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED
android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED
android.app.action.NOTIFICATION_POLICY_CHANGED
android.app.action.PROFILE_OWNER_CHANGED
android.app.action.PROFILE_PROVISIONING_COMPLETE
android.app.action.SYSTEM_UPDATE_POLICY_CHANGED
android.appwidget.action.APPWIDGET_DELETED
android.appwidget.action.APPWIDGET_DISABLED
android.appwidget.action.APPWIDGET_ENABLED
android.appwidget.action.APPWIDGET_HOST_RESTORED
android.appwidget.action.APPWIDGET_RESTORED
android.appwidget.action.APPWIDGET_UPDATE
android.appwidget.action.APPWIDGET_UPDATE_OPTIONS
android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED
android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED
android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
android.bluetooth.adapter.action.DISCOVERY_FINISHED
android.bluetooth.adapter.action.DISCOVERY_STARTED
android.bluetooth.adapter.action.LOCAL_NAME_CHANGED
android.bluetooth.adapter.action.SCAN_MODE_CHANGED
android.bluetooth.adapter.action.STATE_CHANGED
android.bluetooth.device.action.ACL_CONNECTED
android.bluetooth.device.action.ACL_DISCONNECTED
android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED
android.bluetooth.device.action.BOND_STATE_CHANGED
android.bluetooth.device.action.CLASS_CHANGED
android.bluetooth.device.action.FOUND
android.bluetooth.device.action.NAME_CHANGED
android.bluetooth.device.action.PAIRING_REQUEST
android.bluetooth.device.action.UUID
android.bluetooth.devicepicker.action.DEVICE_SELECTED
android.bluetooth.devicepicker.action.LAUNCH
android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT
android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED
android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED
android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED
android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED
android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED
android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED
android.content.pm.action.SESSION_COMMITTED
android.hardware.action.NEW_PICTURE
android.hardware.action.NEW_VIDEO
android.hardware.hdmi.action.OSD_MESSAGE
android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS
android.hardware.usb.action.USB_ACCESSORY_ATTACHED
android.hardware.usb.action.USB_ACCESSORY_DETACHED
android.hardware.usb.action.USB_DEVICE_ATTACHED
android.hardware.usb.action.USB_DEVICE_DETACHED
android.intent.action.ACTION_POWER_CONNECTED
android.intent.action.ACTION_POWER_DISCONNECTED
android.intent.action.ACTION_SHUTDOWN
android.intent.action.AIRPLANE_MODE
android.intent.action.APPLICATION_RESTRICTIONS_CHANGED
android.intent.action.BATTERY_CHANGED
android.intent.action.BATTERY_LOW
android.intent.action.BATTERY_OKAY
android.intent.action.BOOT_COMPLETED
android.intent.action.CAMERA_BUTTON
android.intent.action.CLOSE_SYSTEM_DIALOGS
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.CONTENT_CHANGED
android.intent.action.DATA_SMS_RECEIVED
android.intent.action.DATE_CHANGED
android.intent.action.DEVICE_STORAGE_LOW
android.intent.action.DEVICE_STORAGE_OK
android.intent.action.DOCK_EVENT
android.intent.action.DOWNLOAD_COMPLETE
android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED
android.intent.action.DREAMING_STARTED
android.intent.action.DREAMING_STOPPED
android.intent.action.DROPBOX_ENTRY_ADDED
android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE
android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE
android.intent.action.FACTORY_RESET
android.intent.action.FETCH_VOICEMAIL
android.intent.action.GTALK_CONNECTED
android.intent.action.GTALK_DISCONNECTED
android.intent.action.HEADSET_PLUG
android.intent.action.HEADSET_PLUG
android.intent.action.INPUT_METHOD_CHANGED
android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION
android.intent.action.LOCALE_CHANGED
android.intent.action.LOCKED_BOOT_COMPLETED
android.intent.action.MANAGE_PACKAGE_STORAGE
android.intent.action.MASTER_CLEAR_NOTIFICATION
android.intent.action.MEDIA_BAD_REMOVAL
android.intent.action.MEDIA_BUTTON
android.intent.action.MEDIA_CHECKING
android.intent.action.MEDIA_EJECT
android.intent.action.MEDIA_MOUNTED
android.intent.action.MEDIA_NOFS
android.intent.action.MEDIA_REMOVED
android.intent.action.MEDIA_SCANNER_FINISHED
android.intent.action.MEDIA_SCANNER_SCAN_FILE
android.intent.action.MEDIA_SCANNER_STARTED
android.intent.action.MEDIA_SHARED
android.intent.action.MEDIA_UNMOUNTABLE
android.intent.action.MEDIA_UNMOUNTED
android.intent.action.MY_PACKAGE_REPLACED
android.intent.action.NEW_OUTGOING_CALL
android.intent.action.NEW_VOICEMAIL
android.intent.action.PACKAGES_SUSPENDED
android.intent.action.PACKAGES_UNSUSPENDED
android.intent.action.PACKAGE_ADDED
android.intent.action.PACKAGE_CHANGED
android.intent.action.PACKAGE_DATA_CLEARED
android.intent.action.PACKAGE_FIRST_LAUNCH
android.intent.action.PACKAGE_FULLY_REMOVED
android.intent.action.PACKAGE_INSTALL
android.intent.action.PACKAGE_NEEDS_VERIFICATION
android.intent.action.PACKAGE_REMOVED
android.intent.action.PACKAGE_REPLACED
android.intent.action.PACKAGE_RESTARTED
android.intent.action.PACKAGE_VERIFIED
android.intent.action.PHONE_STATE
android.intent.action.PROVIDER_CHANGED
android.intent.action.PROXY_CHANGE
android.intent.action.QUERY_PACKAGE_RESTART
android.intent.action.REBOOT
android.intent.action.SCREEN_OFF
android.intent.action.SCREEN_ON
android.intent.action.SIM_STATE_CHANGED
android.intent.action.TIMEZONE_CHANGED
android.intent.action.TIME_SET
android.intent.action.TIME_TICK
android.intent.action.UID_REMOVED
android.intent.action.UMS_CONNECTED
android.intent.action.UMS_DISCONNECTED
android.intent.action.USER_PRESENT
android.intent.action.USER_UNLOCKED
android.intent.action.WALLPAPER_CHANGED
android.media.ACTION_SCO_AUDIO_STATE_UPDATED
android.media.AUDIO_BECOMING_NOISY
android.media.RINGER_MODE_CHANGED
android.media.SCO_AUDIO_STATE_CHANGED
android.media.VIBRATE_SETTING_CHANGED
android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION
android.media.action.HDMI_AUDIO_PLUG
android.media.action.MICROPHONE_MUTE_CHANGED
android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION
android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED
android.media.tv.action.INITIALIZE_PROGRAMS
android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT
android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED
android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED
android.net.conn.BACKGROUND_DATA_SETTING_CHANGED
android.net.conn.CONNECTIVITY_CHANGE
android.net.conn.RESTRICT_BACKGROUND_CHANGED
android.net.nsd.STATE_CHANGED
android.net.scoring.SCORER_CHANGED
android.net.scoring.SCORE_NETWORKS
android.net.wifi.NETWORK_IDS_CHANGED
android.net.wifi.RSSI_CHANGED
android.net.wifi.SCAN_RESULTS
android.net.wifi.STATE_CHANGE
android.net.wifi.WIFI_STATE_CHANGED
android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED
android.net.wifi.p2p.CONNECTION_STATE_CHANGE
android.net.wifi.p2p.DISCOVERY_STATE_CHANGE
android.net.wifi.p2p.PEERS_CHANGED
android.net.wifi.p2p.STATE_CHANGED
android.net.wifi.p2p.THIS_DEVICE_CHANGED
android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED
android.net.wifi.supplicant.CONNECTION_CHANGE
android.net.wifi.supplicant.STATE_CHANGE
android.nfc.action.ADAPTER_STATE_CHANGED
android.nfc.action.TRANSACTION_DETECTED
android.os.action.DEVICE_IDLE_MODE_CHANGED
android.os.action.POWER_SAVE_MODE_CHANGED
android.provider.Telephony.SECRET_CODE
android.provider.Telephony.SIM_FULL
android.provider.Telephony.SMS_CB_RECEIVED
android.provider.Telephony.SMS_DELIVER
android.provider.Telephony.SMS_RECEIVED
android.provider.Telephony.SMS_REJECTED
android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED
android.provider.Telephony.WAP_PUSH_DELIVER
android.provider.Telephony.WAP_PUSH_RECEIVED
android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED
android.provider.action.EXTERNAL_PROVIDER_CHANGE
android.provider.action.SYNC_VOICEMAIL
android.security.STORAGE_CHANGED
android.security.action.KEYCHAIN_CHANGED
android.security.action.KEY_ACCESS_CHANGED
android.security.action.TRUST_STORE_CHANGED
android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED
android.speech.tts.engine.TTS_DATA_INSTALLED
android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED
android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED
android.telephony.action.REFRESH_SUBSCRIPTION_PLANS
android.telephony.action.SIM_APPLICATION_STATE_CHANGED
android.telephony.action.SIM_CARD_STATE_CHANGED
android.telephony.action.SIM_SLOT_STATUS_CHANGED
android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED
android.telephony.euicc.action.NOTIFY_CARRIER_SETUP
android.telephony.euicc.action.OTA_STATUS_CHANGED


总结

  • 本文全面的介绍Android中的广播机制,对广播的发送,接受,以及Android新版本的变化等方方面面做出详细的总结。
  • 笔者水平有限,如有错漏,欢迎指正。
  • 接下来我也会将所学的知识分享出来,有兴趣可以继续关注whd_Alive的Android开发笔记
  • 不定期分享Android开发相关的技术干货,期待与你的交流,共勉。

更多相关文章

  1. Android监听应用程序安装和卸载
  2. Android(安卓)NDK 开发
  3. android adb 命令发送 keyevent
  4. Android之短信发送器
  5. android 呼入电话的监听(来电监听)转
  6. android 里使用Socket进行发送消息案例
  7. Android(安卓)中的BroadCastReceiver
  8. android邮件发送几种方式
  9. Android(安卓)面试题(2)

随机推荐

  1. Android通过selector改变界面状态
  2. android的进度条使用
  3. Android(安卓)studio升级AndroidX
  4. About Android; Geocoder, “the service
  5. Android(安卓)- Android(安卓)Studio 自
  6. android工程下轻松运行java main程序
  7. android SharedPreferences 使用
  8. Android(安卓)Studio 默认debug证书位置
  9. 基于TCP/IP协议的Java服务端与Android客
  10. Android使用系统方法实现分享到QQ和微信!