Android Broadcast 探索(二)— 使用

一、Android 广播机制包括 3 个基本要素:

  • 发送广播的 Broadcast;

  • 接受广播的 BroadcastReceiver;

  • 用于传递信息的 Intent;

二、发送广播

Android 为应用程序发送广播提供了三种方式:

2.1 sendOrderedBroadcast(Intent, String) — 有序广播

sendOrderedBroadcast(Intent, String) 方法一次向一个接收器发送广播。当每个接收器依次执行时,它可以将结果传播到下一个接收器,它也可以完全中止广播,使其不会传递给其他接收器。receiver 的运行顺序可以通过匹配的 intent-filterandroid:priority 属性进行控制;具有相同优先级的接收器将以任意顺序运行。

2.2 sendBroadcast(Intent) — 普通广播

sendBroadcast(Intent) 方法以随机的顺序向所有接收者发送广播。这被称为普通广播。这样更有效率,但意味着 receiver 无法读取其他 receiver 的结果、传播从其他广播接收的数据以及中止广播。

2.3 LocalBroadcastManager.sendBroadcast — 本地广播

LocalBroadcastManager.sendBroadcast() 方法将广播发送到与发送者位于同一应用程序中的接收者。如果你不需要跨应用发送广播,请使用本地广播。实现效率更高(不需要进程间通信),而且无需担心其他应用程序能够接收或发送你的广播。

以下代码片段演示了如何通过创建一个 Intent 并调用 sendBroadcast(Intent) 来发送广播。

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice me senpai!");
sendBroadcast(intent);

广播消息被包裹在一个 Intent 对象中。Intent 的 action 字符串必须提供应用程序的 Java 包名称并唯一标识广播事件。你可以将附加信息通过 putExtra(String, Bundle) 添加到 intent 中。你也可以通过调用 setPackage(String) 限制发送的应用程序。

注意:尽管 intent 用于发送广播和启动活动 (startActivity(Intent)),但这些操作完全不相关。

三、使用权限限制广播

权限允许你将广播限制为拥有特定权限的应用程序集。你可以对广播的发送者或接收者实施限制。

3.1 带权限发送

当你调用 sendBroadcast(Intent, String) 或者 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle),你可以指定一个权限参数。只有接收方已经在 manifest 中标记了权限(并且授予许可,如果该权限存在危险)才可以接收广播。例如,下面的代码发送一个广播:

sendBroadcast(new Intent("com.example.NOTIFY"),
              Manifest.permission.SEND_SMS);

要接收广播,应用程序必须请求权限,如下所示:

<uses-permission android:name="android.permission.SEND_SMS"/>

注意:自定义权限是在安装应用程序时注册的。定义自定义权限的应用程序必须在使用之前安装。

3.2 带权限接收

如果你在注册 receiver 时指定一个权限参数(无论是在 manifest 的 <receiver> 标签中,还是通过 registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)),那么只有在 manifest 中通过 <uses-permission> 标签请求该权限的应用程序 (并且授予许可,如果该权限存在危险)可以发送 intent 给该 receiver。

例如,假设你的接收应用程序具有如下所示的接收器声明:

<receiver android:name=".MyBroadcastReceiver"
          android:permission="android.permission.SEND_SMS">
    <intent-filter>
        <action android:name="android.intent.action.AIRPLANE_MODE"/>
    </intent-filter>
</receiver>

或者你的接收应用程序有一个上下文注册的接收器,如下所示:

IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null );

那么,为了能够向这些接收方发送广播,发送方必须请求权限,如下所示:

<uses-permission android:name="android.permission.SEND_SMS"/>

四、安全考虑和最佳做法

以下是发送和接收广播的一些安全考虑事项和最佳做法:

  • 如果你不需要将广播发送到你的应用以外的组件,则可以使用 LocalBroadcastManager 发送和接收本地广播。LocalBroadcastManager 效率要高得多(不需要进程间通信),并可以让你避免其他应用程序能够接收或发送你的广播。本地广播可以在你的应用程序中作为通用的 pub/sub event bus,而无需系统广播的任何开销。

  • 如果许多应用程序已经在 manifest 中注册相同的广播,则可能会导致系统启动大量应用程序,从而对设备性能和用户体验产生重大影响。为了避免这种情况,优先使用 context 方式注册广播。有时,Android 系统本身会强制使用上下文注册的接收器。例如,CONNECTIVITY_ACTION 广播仅传送给上下文注册的接收器。

  • 不要使用隐式 intent 传播敏感信息。任何注册了接收该广播的应用程序都可以读取信息。有三种方法可以限制哪些应用能够接收你的广播:

    • 可以在发送广播时指定权限。

    • 在 Android 4.0 及更高版本,可以通过 setPackage(String) 指定包名。

    • 可以使用 LocalBroadcastManager 发送广播。

  • 当你注册 receiver 时,任何应用程序都可能将潜在的恶意广播发送到你应用的 receiver。有三种方法可以限制你的应用可以收到哪些广播:**

    • 可以在注册广播接收器时指定权限。

    • 对于 manifest 声明的 receiver,可以在清单中将 android:exported 属性设置为 “false”。这样 receiver 就不接收来自应用程序外部的广播。

    • 可以通过 LocalBroadcastManager 限制只有本地广播。

  • 广播动作 (action) 的命名空间是全局的。确保动作名称和其他字符串被写入您拥有的名称空间中,否则可能会无意中与其他应用程序发生冲突。

  • 因为 receiver 的 onReceive(Context, Intent) 方法在主线程上运行,所以它应该快速执行并返回。如果你需要执行长时间运行的工作,请注意开启子线程或启动后台服务,因为系统可能会在 onReceive() 返回后终止整个进程 。建议:

    • 在 receiver 的 onReceive() 方法中调用 goAsync() 方法并传递 BroadcastReceiver.PendingResult 给后台线程。这使广播从 onReceive() 返回后依旧保持活动状态。但是,即使采用这种方法,系统也希望你能够很快结束广播(不到 10 秒)。不过,它确实允许你将工作移至另一个线程以避免妨碍主线程。

    • 使用 JobScheduler 安排工作。

  • 不要从广播接收器启动活动,因为很影响用户体验;特别是如果有多个接收器的话。相反,请考虑执行显示通知等简单操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Broadcasts Android apps can send or receive broadcast mes...
    woitaylor阅读 6,144评论 0 12
  • 【Android 广播】 BroadcastReceiver简介 BroadcastReceiver(广播接收器)...
    Rtia阅读 3,380评论 1 17
  • 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,Broadca...
    IT小魔女的故事阅读 548评论 0 2
  • 前言:本文所写的是博主的个人见解,如有错误或者不恰当之处,欢迎私信博主,加以改正! 原文链接,demo链接 广播简...
    PassersHowe阅读 3,436评论 0 9
  • 1.资源库 来自我内心对一些情绪的热爱和挥之不去的记忆是我想要写作的源头,我想用最美好的文字歌颂它们。 喜欢读散文...
    迷鹿人阅读 279评论 1 2