什么是Broadcast

Broadcast即广播,在Android广播是很重要的功能。比如我们想在系统开机之后做某些事情、监控手机的电量、监控手机的网络状态等等。这些功能都须要用到广播。当然我们也能够自己定义广播。

自己定义广播

通常实现一个简单的自己定义广播能够通过例如以下几个步骤:

  • 创建一个类继承android.content.BroadcastReceiver,并实现onReceive方法
  • 在AndroidManifest.xml中注冊广播
  • 通过Context的registerReceiver等方法注冊广播
  • 调用Context的sendBroadcast等方法发送广播,在onReceive方法中处理广播
  • 调用Context的unregisterReceiver等方法注销广播

我们通过代码来解释一下上面的步骤:

1.创建一个类继承android.content.BroadcastReceiver。并实现onReceive方法

package com.mark.broadcastreciver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log; /**
* 创建一个自己定义广播接收者须要继承android.content.BroadcastReceiver,
* 并实现onReceive方法就可以。
*/
public class MyReceiver extends BroadcastReceiver { private final static String TAG = MyReceiver.class.getSimpleName(); public MyReceiver() {
} /**
* 当接收到广播之后会调用此方法
* @param context 上下文对象
* @param intent 调用sendBroadcast(intent)传入的Intent实例,当中包括了action、和其它附带信息
*/
@Override
public void onReceive(Context context, Intent intent) {
// 获取msg相应的数据
String msg = intent.getStringExtra("msg");
// 打印msg数据
Log.i(TAG, "msg = " + msg);
// 打印action字符串
Log.i(TAG, "action = " + intent.getAction());
}
}

2.在AndroidManifest.xml中注冊广播

<application>
<receiver android:name=".MyReceiver">
</receiver>
</application>

3.通过Context的registerReceiver等方法注冊广播

4.调用Context的sendBroadcast等方法发送广播。在onReceive方法中处理广播

5.调用Context的unregisterReceiver等方法注销广播

package com.mark.broadcastreciver;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View; public class MainActivity extends AppCompatActivity { BroadcastReceiver registerReceiver;
IntentFilter intentFilter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 创建BroadcastReceiver实例
registerReceiver = new MyReceiver();
// 创建IntentFilter。指定其action为com.mark.broadcast.receiver,这个能够自己定义
intentFilter = new IntentFilter("com.mark.broadcast.receiver");
// 注冊广播将registerReceiver与intentFilter关联,
// registerReceiver能够接收到action为com.mark.broadcast.receiver的广播
registerReceiver(registerReceiver, intentFilter); findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 发送广播 // 创建Intent。指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致
Intent intent = new Intent("com.mark.broadcast.receiver");
// 指定要发送的信息
intent.putExtra("msg", "Hello, a new message.");
sendBroadcast(intent);
}
}); } @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(registerReceiver);
}
}

通过上述的步骤我们就实现了一个自己定义广播,当我们点击Button在控制台中能够看到例如以下信息:

04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: msg = Hello, a new message.
04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: action = com.mark.broadcast.receiver

注冊广播

注冊广播的方式有两种:静态注冊和动态注冊。

静态注冊

这样的方法是在配置AndroidManifest.xml配置文件里注冊,通过这样的方式注冊的广播为常驻型广播,也就是说假设应用程序关闭了。有相应事件触发。程序还是会被系统自己主动调用执行。

比如:

<!-- 在配置文件里注冊BroadcastReceiver能够匹配的Intent -->
<receiver android:name=“.MyReceiver">
<intent-filter>
</action>
<action android:name=“com.mark.broadcast.reveiver”/>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</receiver>

动态注冊

这样的方法是通过代码在.Java文件里进行注冊。通过这样的方式注冊的广播为很驻型广播,即它会尾随Activity的生命周期,所以在Activity结束前我们须要调用unregisterReceiver(receiver)方法移除它。比如:

// 创建BroadcastReceiver实例
registerReceiver = new MyReceiver();
// 创建IntentFilter,指定其action为com.mark.broadcast.receiver。这个能够自己定义
intentFilter = new IntentFilter("com.mark.broadcast.receiver");
// 注冊广播将registerReceiver与intentFilter关联。
// registerReceiver能够接收到action为com.mark.broadcast.receiver的广播
registerReceiver(registerReceiver, intentFilter);

注意:假设我们在Activity中注冊了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注冊否则会出现异常。方法例如以下:

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(registerReceiver);
}

广播的类型

Broadcast的类型有两种:普通广播和有序广播。

Normal broadcasts (普通广播)

Normal broadcasts是全然异步的能够同一时间被全部的接收者接收到。消息的传递效率比較高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播。多个普通广播设置同样的IntentFilter,则先注冊的先收到广播。

Ordered broadcasts (有序广播)

Ordered broadcasts的接收者依照一定的优先级进行消息的接收。

如:A,B,C的优先级依次减少。那么消息先传递给A,在传递给B,最后传递给C。

优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。

另外Ordered broadcasts的接收者能够通过abortBroadcast()的方式取消广播的传播,也能够通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。

然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。

比如:

<receiver
android:name=".FirstReceiver"> <intent-filter
android:priority="999">
<action android:name="com.mark.broadcast.receiver" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver" >
<intent-filter
android:priority="1000">
<action android:name="com.mark.broadcast.receiver" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

如上两个receiver我们分别设置为priority为999,和1000。及时MyReceiver是后注冊的,可是其优先级比FirstReceiver高,则MyReceiver会先处理广播。

sendOrderedBroadcast 发送有序广播

sendOrderedBroadcast(intent, receiverPermission)方法接收两个參数。比普通广播的发送方式多了一个receiverPermission參数。这是一个String类型的參数,代表具有这个权限的Receiver才干处理收到此广播。假设为null则表明不要求接受者声明指定权限。我们来看一下详细的操作。

首先我们要自己定义一个权限。比如:

<permission
android:name="com.permissions.MY_BROADCAST_RECEIVER"
android:protectionLevel="normal" />

然后我们要是当前的程序具有此权限:比如:

<uses-permission android:name="com.permissions.MY_BROADCAST_RECEIVER" />

这样当前程序就拥有此权限了。

我们在发送有序广播是指定其权限为com.permissions.MY_BROADCAST_RECEIVER。注意拼写不要有错误,最好是复制过来。

发送广播例如以下:

// 创建Intent,指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致
Intent intent = new Intent("com.mark.broadcast.receiver");
// 指定要发送的信息
intent.putExtra("msg", "Hello, a new message.");
sendOrderedBroadcast(intent, "com.permissions.MY_BROADCAST_RECEIVER");

这样我们发送广播,并指定其权限为com.permissions.MY_BROADCAST_RECEIVER,由于当前的程序已经使用了此权限了。所以当前程序中的receiver是能够接收并处理此条广播的。否则不能接收此条广播。此处的权限体现了android对安全性的重视。

sendStickyBroadcast 粘性广播

粘性广播与其它的广播方式最大的不同在于“异步”,也就是说当一个粘性广播发出去后,能够没有Receiver进行处理。可是这个广播还会一直存在,假如过了一段时间之后有Receiver注冊了此广播,则此Receiver还是能够处理这条广播的。可是细心的朋友们能够看到sendStickyBroadcast的一系列重载方法的參数中并没有上面提到的receiverPermission參数,这也将导致粘性广播在安全性上存在问题。

所以在API Level 21 上sendStickyBroadcast方法被标记为deprecated。也就是不建议我们使用粘性广播了。由于在安全性和其它方面粘性广播存在许多缺陷。这里我们也就不在重点讨论了。

总结

这里我们对广播及广播接收者进行一个简单的总结以及在使用时的一些注意事项。

1.发送广播的方法都是ContextWrapper中的方法。而Activity、Service都是ContextWrapper的子类,所以在它们中都能够发送和注冊广播

2.onReceive方法中不能做耗时操作,否则也会导致ANR

3.依据实际开发须要。尽可能为广播添加权限

4.尽可能避免使用粘性广播

5.有序广播的优先级为【-1000 ~ 1000】,数值越大。优先级越高

上述描写叙述和某些观点可能不是正解,仅供參考,欢迎大家指正、批评。

Android-BroadcastReceiver具体解释的更多相关文章

  1. android BroadcastReceiver ACTION_TIME_TICK 系统时间监听不到

    android BroadcastReceiver ACTION_TIME_TICK 系统时间监听不到 今天做android上的消息推送,启动了一个独立service,然后在里面监听系统的ACTION ...

  2. Android slidingmenu详细解释 滑动的优化

    Android slidingmenu 详细解释 性能优化 转载请注明:   http://blog.csdn.net/aaawqqq 简单介绍 SlidingMenu 是github 上Androi ...

  3. android动画具体解释一 概述

    动画和图形概述 Android 提供了大量的强大的API以应用于UI动画和绘制2D和3D图形.以下各节向你描写叙述了这些API的预览和系统能力以帮助你决定怎么才是达到你需求的最佳方法. 动画 Andr ...

  4. android动画具体解释二 属性动画原理

    property动画是一个强大的框架,它差点儿能使你动画不论什么东西. 你能够定义一个动画来改变对象的不论什么属性,不论其是否被绘制于屏幕之上. 一个属性动画在一定时间内多次改变一个属性(对象的一个字 ...

  5. Android Scroll具体解释(二):OverScroller实战

    作者: ztelur 联系方式:segmentfault,csdn.github 本文仅供个人学习,不用于不论什么形式商业目的,转载请注明原作者.文章来源.链接,版权归原文作者全部.  本文是andr ...

  6. android动画具体解释六 XML中定义动画

    动画View 属性动画系统同意动画View对象并提供非常多比view动画系统更高级的功能.view动画系统通过改变绘制方式来变换View对象,view动画是被view的容器所处理的,由于View本身没 ...

  7. android动画具体解释四 创建动画

    使用ValueAnimator进行动画 通过指定一些int, float或color等类型的值的集合.ValueAnimator 使你能够对这些类型的值进行动画.你需通过调用ValueAnimator ...

  8. 使用Ant打包Android应用具体解释——Ant使用解析

    上篇<使用Ant打包Android应用具体解释>描写叙述了使用Ant打包的流程,但非常多步骤并没有说明如此做的原因,本篇将从Ant方面来理解,下一篇从APK生成的流程来说明. APK包的生 ...

  9. Android BroadcastReceiver 简介

    Android BroadcastReceiver 简介  在 Android 中使用 Activity, Service, Broadcast, BroadcastReceiver     活动(A ...

  10. 4、android BroadcastReceiver详细用法

    BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播. 在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这 ...

随机推荐

  1. 【Mybatis】未封装返回结果的字段自己返回值的问题

    在spring boot中使用mybatis过程中,发现有个实体的时间字段未在mapper方法执行完的封装结果中进行封装,但是却有值返回. 如下展示问题: 实体如下: package com.sxd. ...

  2. ubuntu 下安装nodejs以及pm2

    ubuntu 12.04服务器可以使用apt-get方式安装Node JS,但是,安装完后的版本为v0.6.12的版本,如果我们想要使用新一点的版本需要做如下配置: 1 2 3 4 apt-get i ...

  3. webstorm编辑器设置为vim的方法

    首先有这个插件,其设置如下,选中即可 打开和关闭方法: https://www.jetbrains.com/help/webstorm/vim-emulation.html https://plugi ...

  4. Shell--变量内容的删除、替代与替换

    1. 变量内容的删除与替换 #代表由前面开始删除,所以这里便由开始的/删起,*来代替0到无穷多个任意字符 %由后面向前删除变量内容 例如:echo ${path%:*bin}删除最有一个目录,即从:到 ...

  5. YOLO 测试出错:段错误 (核心已转储)

    段错误 (核心已转储): data/voc.names中文标签改成英文

  6. angular 中的$event 对象包含了浏览器原生的event对象

    ou can pass the $event object as an argument when calling the function. The $event object contains t ...

  7. Java List序列化的实现

    概述 java中的序列化与反序列化都要求对象实现Serializable接口(其实就是声明一下),而对于List这种动态改变的集合默认是不实现这个接口的,也就是不能直接序列化.但是数组是可以序列化的, ...

  8. 字符串截取 及 substr 和 substring 的区别

    1..字符串截取 str.substr(0, 1) // 获取字符串第一个字符 str.substr(-1) // 获取字符串最后一个字符 str.charAt(str.length - 1) // ...

  9. mongo 增

    mongodb存储的是文档,文档是json格式的对象,我们的增删改查,都要传输json对象 json是一个对象,js里有数组这个概念,只需要把多个对象放到一个数组里,即可 use test //首先选 ...

  10. KingdeeK3-修改单据邮件发送的自定义字段

    只需要执行类似下面语句即可: update ICTemplateentry set FVisForBillType = 63,flookupcls=6 where fid ='P01' and fhe ...