Android 浅析 Broadcast (一) 使用

原文链接:https://jasonzhong.github.io/2016/09/18/Android-%E6%B5%85%E6%9E%90-Broadcast-%E4%B8%80-%E4%BD%BF%E7%94%A8/

前言

Linus Benedict Torvalds : RTFSC – Read The Funning Source Code

概括

广播(Broadcast)是在组件之间传播数据(Intent)的一种机制。通过Broadcast发送者和接收者,并且不需要知道对方存在。

使用

Step 1. 创建接收类

创建一个接收类继承BroadcastReceiver类,并覆写onReceive()方法。

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {}
}

Step 2. 注册广播接收器

1.静态注册

<application >
    <receiver 
        android:name=".MyBroadcastReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="com.unknow.jason.broadcasttest.MY_BROADCAST"/>
        </intent-filter>
    </receiver>
</application>

2.动态注册

intentFilter = new IntentFilter();
intentFilter.addAction("com.unknow.jason.broadcasttest.MY_BROADCAST");

myBroadcastReceiver = new MyBroadcastReceiver();
registerReceiver(myBroadcastReceiver, intentFilter);

unregisterReceiver(myBroadcastReceiver);

Step 3. 发送广播

Intent intent = new Intent("com.unknow.jason.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);

详细使用

静态注册字段

字段 解释
android:banner A Drawable resource providing an extended graphical banner for its associated item. 一个Drawable资源为其相关联的项目提供扩展的图形横幅。
android:description Descriptive text for the associated data. 为关联数据提供描述。
android:directBootAware Indicate if this component is aware of direct boot lifecycle, and can be safely run before the user has entered their credentials (such as a lock pattern or PIN). 指示此组件是否知道直接引导生命周期,并且可以在用户输入其凭据(例如锁定模式或PIN)之前安全运行。
android:enabled Specify whether the receiver is enabled or not (that is, can be instantiated by the system). 指定这个接收者是否被开启。是否被系统注册。
android:exported Flag indicating whether the given application component is available to other applications. 指示给定应用程序组件是否可用于其他应用程序的标志。
android:icon A Drawable resource providing a graphical representation of its associated item. 一个可绘制的资源,提供其关联项目的图形表示。
android:label A user-legible name for the given item. 给定项目的用户可读名称。
android:logo A Drawable resource providing an extended graphical logo for its associated item. 一个Drawable资源,为其相关联的项目提供扩展的图形标志。
android:name Required name of the class implementing the receiver, deriving from BroadcastReceiver. 实现接收器的类的所需名称,源自BroadcastReceiver。
android:permission Specify a permission that a client is required to have in order to use the associated object. 指定客户机必须具有的权限才能使用关联的对象。
android:process Specify a specific process that the associated code is to run in. 指定一个指定的进程让关联的代码在此上运行。
android:roundIcon A Drawable resource providing a graphical representation of its associated item. 一个可绘制的资源,提供其关联项目的图形表示。
android:singleUser If set to true, a single instance of this component will run for all users. 如果设置为true,则此组件的单个实例将为所有用户运行。

LocalBroadcastManager

Helper to register for and send broadcasts of Intents to local objects within your process.帮助程序注册和发送Intents的广播到您的进程中的本地对象。

与使用sendBroadcast(Intent)发送全局广播相比,这具有许多优点:

  1. 您知道您正在播送的数据不会离开您的应用,因此不需要担心泄露私人数据。
  2. 其他应用程序不可能将这些广播发送到您的应用程序,因此您不必担心它们可以利用的安全漏洞。
  3. 它比通过系统发送全局广播更有效。

主要使用方法:

返回值 函数 解释
static LocalBroadcastManager getInstance(Context context)
void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) Register a receive for any local broadcasts that match the given IntentFilter.
boolean sendBroadcast(Intent intent) Broadcast the given intent to all interested BroadcastReceivers.
void sendBroadcastSync(Intent intent) Like sendBroadcast(Intent), but if there are any receivers for the Intent this function will block and immediately dispatch them before returning.
void unregisterReceiver(BroadcastReceiver receiver) Unregister a previously registered BroadcastReceiver.

主要类

BroadcastReceiver

Base class for code that will receive intents sent by sendBroadcast().
翻译:基础类可以接受来自sendBroadcast()发出的intents。

如果你不需要在应用程序发送广播,考虑使用localbroadcastmanager类代替接下来描述的一般工具。这会给你一个更有效的实现(无需跨进程通信),并允许您避免考虑与其他应用程序能够接收或发送广播任何安全问题。

您可以动态地注册这个类用Context.registerReceiver()方法或静态的实例,通过发布在AndroidManifest.xml中的<接收>标记的实现。

注意:如果注册一个接收器在Activity.onResume()函数,你需要反注册在Activity.onPause(). 这将减少不必要的系统开销。不要在Activity.onSaveInstanceState()注册。

有两个主要的类的广播可以用来接收。

  1. 普通广播:(使用 Context.sendBroadcast发出)是完全异步的。所有接收者都运行在一个未定义的顺序里,有时甚至同时接收。这很高效,但也意味着不能使用结束或暂停API。
  2. 有序广播:(使用 Context.sendOrderedBroadcast发出)同一时间只传递一个接收器。每个接收器依次执行,它可以传送结果到下一个接收器,当然也可以暂停传送。这个顺序在android:priority属性里通过 intent-filter定义,如果定义同样的优先级则是随机顺序。

安全性

有这么几点建议:

  1. 这个Intent的命名空间是全局的。
  2. 当你使用registerReceiver(),任何应用程序可以向该注册的接收者发送广播。你可以控制谁可以通过定义的权限发送广播到它。
  3. 当你在应用程序的清单中发布一个接收器并为它指定一个IntentFilter,任何其他应用程序都可以发送到它的广播,不管你指定的筛选器。为了防止别人发送到它,使他们无法使用安卓:android:exported="false"。
  4. 当你使用sendBroadcast(Intent)或者相关方法,一般任何其他应用程序都可以接收这些广播。你可以通过定义的权限控制谁可以接收这些广播。另外,从ice_cream_sandwich,你也可以安全限制广播到单个应用程序利用Intent.setpackage。

接收者的生命周期

一个广播接收者有一个回调方法:void onReceive()。当一个广播消息到达接收者时,Android调用它的onReceive()方法并传递给它包含消息的Intent对象。广播接收者被认为仅当它执行这个方法时是活跃的。当onReceive()返回后,它是不活跃的。有一个活跃的广播接收者的进程是受保护的,不会被杀死。但是系统可以在任何时候杀死仅有不活跃组件的进程,当占用的内存别的进程需要时。
特别是,你可能不会显示一个对话框或绑定到一个服务在一个BroadcastReceiver中。对于前者,你应该使用NotificationManager API。对于后者,你可以使用上下文:startservice()将命令发送到服务。

进程的生命周期

一个进程,目前正在执行一个BroadcastReceiver(即目前在运行onReceive代码(Context,Intent)函数)被认为是一个前台进程将保持运行的系统除了在极端的内存压力下。
这意味着如果想保持进程长时间运行可以经常利用一个服务去调用BroadcastReceiver来保持进程不被删除

onReceive()

这个方法是当BroadcastReceiver收到一个Intent broadcast消息是被调用。该方法是在其进程的主线程调用的,除非明确地要求运行在不同的线程利用registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)这个函数。不允许在主线程做耗时的任务,因此也不要onreceive()推出弹出对话框。
如果这个BroadcastReceiver通过<receiver>标签发送,当这个函数返回后这个对象将不在存在。这意味着你不应该进行任何操作在返回结果后特别是异步,对正在互动的服务,应该用startService(Intent)代替bindService(Intent, ServiceConnection, int)。如果你希望和正在运行的服务互动,应该调用peekService(Context, Intent)。
被用在registerReceiver(BroadcastReceiver, IntentFilter) 和application manifests的IntentFilter不保证独有。onReceive()实现应该只对已知的action作出反应,忽略那些未知的被收到的Intent。

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

推荐阅读更多精彩内容