什么是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. 【Node.js】4.从一个例子切入Node js的规范

    在开始之前,需要明确的一点就是, ①Node应用是由模块组成的,每一个文件都是一个模块,有自己的作用域. ②在这个文件里定义的变量,函数,类都是私有的,对其他的文件不可见. ③在一个文件中,也就是在一 ...

  2. jq和js中click 事件的几种方式总结和click事件的累加问题解决办法

     1:常见的三种绑定click事件: 第一种:$("#click").click(function(){ alert("Hello World  click") ...

  3. linux 多线程那点事

    说明:对多线程与相互排斥锁不熟悉的请參考其他 #include <pthread.h> #include <stdio.h> #include <stdlib.h> ...

  4. pc_lint的用法转

    PC-Lint是一款C/C++软件代码静态分析工具,不仅可以检查一般的语法错误,还可以检查潜在的错误,比如数组访问越界.内存泄漏.使用未初始化变量.使用空指针等.在单元测试前使用PC-Lint来检查代 ...

  5. mac 上python编译报错No module named MySQLdb

    mac 上python编译报错No module named MySQLdb You installed python You did brew install mysql You did expor ...

  6. selenium执行报错:Process refused to die after 10 seconds, and couldn't taskkill it

    十二月 02, 2015 5:16:56 下午 org.openqa.selenium.os.ProcessUtils killWinProcess 警告: Process refused to di ...

  7. zabbix通过snmp监控linux主机

    1.安装net-snmp [root@db01 ~]# yum install -y net-snmp 2.修改配置文件 [root@db01 ~]# vim /etc/snmp/snmpd.conf ...

  8. zabbix自定义监控项一

    1.在agent端配置 1.1 添加自定义监控项 zabbix中监控项叫做item,监控项的取值方法叫做key item: Items是从agnet主机里面获取的所有数据.通常情况下我叫itme为监控 ...

  9. 如何让mysql的自动递增的字段重新从1开始呢?(

    数据库表自动递增字段在用过一段时间后清空,还是继续从清空后的自动编号开始.如何才能让这个字段自动从1开始自动递增呢? 下面两个方法偶都试过,很好用: 1 清空所有数据,将自增去掉,存盘,在加上自增,存 ...

  10. Java Servlet 技术简介 from:IBM Dev

    点评:讲的没有太听懂. from: http://www.ibm.com/developerworks/cn/education/java/j-intserv/index.html#resources