BroadCast的定义:

广播是一种订阅--通知 事件,广播接收者向Android系统 register (订阅广播),广播发送者向Adnroid系统 sendBroadCast(发送广播),然后Android 系统通知所有注册该广播的接收者,广播接收者收到自己注册的广播之后实现自己想做的事情(该事情一般不超过10s,否则应用会出现ANR)。

BroadCast的分类:

1.无序广播:也就是普通广播,只要注册了该action的广播接收者都能收到该广播,且没有先后顺序。

2.有序广播:广播接收者按照优先级高低依次接受该广播,并且优先接收的广播可以通过setResultExtras(Bundle)方法,将处理好的结果传送到下一个广播接收者那里。

3.粘性广播:发送广播调用的方法 sendStickyBroadcast(Intent),和sendBroadcast(Intent)不同。

粘性广播会一直保留在内存当中,直到有广播接收者注册该广播,该广播才算结束。不好解释,等会具体看例子。

BroadCase的使用:

一.普通广播

根据注册方式不同可以分为 静态注册广播和动态注册广播。

1.静态注册广播使用实例

AndroidManifest.xml 如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xjp.mybroadcast"> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <!--静态注册广播,此处需要添加广播的action-->
<receiver android:name=".BroadCastReceive1">
<intent-filter>
<action android:name="com.xjp.mybroadcast.BroadCastReceive1"></action>
</intent-filter>
</receiver>
</application> </manifest>

2.广播接收者实现如下:

package com.xjp.mybroadcast;  

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; public class BroadCastReceive1 extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到广播之后处理自己的事情
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}

3.广播发送者实现如下:

package com.xjp.mybroadcast;  

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button; public class MainActivity extends ActionBarActivity implements View.OnClickListener { private Button btnSend; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this); } @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
} private void sendBraodCast() { /**
* 申明静态广播的 action 行为
*/
String action = "com.xjp.mybroadcast.BroadCastReceive1";
Intent intent = new Intent(action);
intent.putExtra("key", "静态广播测试");
sendBroadcast(intent);
}
}

打印结果如下:

4.静态注册广播特点:

1.注册广播在 AndroidManifest.xml中。

2.广播接收者需重新 继承 BroadcastReceiver 类来实现 onReceive()抽象方法。

3.应用退出无需 注销广播,因此导致:即使广播退出之后,如果有其他应用发送该action行为的广播,此应用还是能接收到该广播的,也就是还会打印上面的 结果。

二.动态广播:

示例

<pre name="code" class="java">package com.xjp.mybroadcast;  

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends ActionBarActivity implements View.OnClickListener {  

    private Button btnSend;  

    private BroadCastReceive2 myReceive;  

    private IntentFilter filter;  

    private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";  

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this); myReceive = new BroadCastReceive2();
filter = new IntentFilter();
filter.addAction(ACTION); } @Override
protected void onResume() {
/**
* 注册广播
*/ LocalBroadcastManager.getInstance(this).registerReceiver(myReceive, filter);//官方建议使用 // this.registerReceiver(myReceive, filter); super.onResume();
} @Override
protected void onPause() {
/**
* 注销广播
*/ LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceive);//官方建议使用 // this.unregisterReceiver(myReceive); super.onPause();
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
} private void sendBraodCast() { /**
* 申明广播的 action 行为
*/
Intent intent = new Intent(ACTION);
intent.putExtra("key", "动态广播测试"); /**
* 官方提倡使用如下发送广播,原因是更快,更安全,不会导致内存泄漏
*/
LocalBroadcastManager.getInstance(this).sendBroadcast(intent); // this.sendBroadcast(intent);
} /**
* 内部类实现广播接收器
*/
private class BroadCastReceive2 extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到广播之后处理自己的事情
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}
}

打印结果如下:

动态广播特点:

1.在代码中调用registerReceiver()方法 注册广播。

2.广播接收者需重新 继承 BroadcastReceiver 类实现内部类。

3.动态广播在应用退出时需要 调用unregisterReceiver()方法来注销广播。如果应用退出时没有注销广播,会报如下错误:



因此,我们通常的做法是:在 onResume()中注册广播,在onPause中注销广播。

4.当广播注销之后就接收不到任何系统发送的广播了。

三.有序广播:

示例:

<pre name="code" class="java">package com.xjp.mybroadcast;  

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button; public class MainActivity extends ActionBarActivity implements View.OnClickListener { private Button btnSend; private BroadCastReceive2 myReceive; private BroadCastReceive3 myReceive3; private IntentFilter filter; private IntentFilter filter3; private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this); myReceive = new BroadCastReceive2();
filter = new IntentFilter();
filter.addAction(ACTION);
filter.setPriority(2);//设置广播的优先级, -1000~1000 ,数字越大,优先级越高。 myReceive3 = new BroadCastReceive3();
filter3 = new IntentFilter();
filter3.addAction(ACTION);
filter3.setPriority(1); } @Override
protected void onResume() {
/**
* 注册广播
*/
registerReceiver(myReceive, filter);
registerReceiver(myReceive3, filter3); super.onResume();
} @Override
protected void onPause() {
/**
* 注销广播
*/ unregisterReceiver(myReceive);
unregisterReceiver(myReceive3); super.onPause();
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
} private void sendBraodCast() { /**
* 申明广播的 action 行为
*/
Intent intent = new Intent(ACTION);
intent.putExtra("key", "有序广播测试"); this.sendOrderedBroadcast(intent, null);
} /**
* 内部类实现广播接收器
*/
private class BroadCastReceive2 extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到广播之后处理自己的事情
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result); Bundle bundle = new Bundle();
bundle.putString("key", "有序广播处理之后" + "\n" + "再次发送给下一个广播接收者");
intent.putExtra("bundle", bundle);
setResultExtras(bundle);
//切断广播,不再让此广播继续往下发送。
// abortBroadcast();
}
} /**
* 内部类实现广播接收器
*/
private class BroadCastReceive3 extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到广播之后处理自己的事情
String action = intent.getAction();
//要不要接受上一个广播接收器receiver2传来的的数据
Bundle bundle = getResultExtras(true);
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + bundle.getString("key"));
}
}
}

有序广播特点:

1.所有广播接收者的action是一致的,发送有序广播调用 sendOrderedBroadcast()方法。

2.有序广播的接收者需要调用setPriority()方法设置广播接收者的优先级。数字越大,优先接受广播。

3.有序广播如果需要终止 广播继续往下发送,可以调用 abortBroadcast()方法切断广播。

4.先接收广播者可以将自己的处理结果通过setResultExtras()方法继续传递给下一个广播接收者。

5.后接收者可以调用 getResultExtras(true)来自己决定是否接收上一个广播传递过来的数据。

四.粘性广播:

需要在 AndroidManifest.xml中添加权限

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

发送广播的Activity

package com.xjp.mybroadcast;  

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button; /**
* 发送广播的Activity
*/
public class MainActivity extends ActionBarActivity implements View.OnClickListener { private Button btnSend; private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive1";
private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive2"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
} private void sendBraodCast() { /**
* 申明广播的 action 行为
*/
Intent intent = new Intent(ACTION);
intent.putExtra("key", "普通广播测试");
sendBroadcast(intent); Intent intent1 = new Intent(ACTION1);
intent1.putExtra("key", "粘性广播测试");
sendStickyBroadcast(intent1);
startActivity(new Intent(this, RecevieActivity.class));
}
}

接受广播的Activity

package com.xjp.mybroadcast;  

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle; /**
* Description:接受广播的Activity
* User: xjp
* Date: 2015/5/14
* Time: 17:03
*/ public class RecevieActivity extends Activity { private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive1";
private final static String ACTION2 = "com.xjp.mybroadcast.BroadCastReceive2"; private Receive receive; private IntentFilter filter1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); receive = new Receive(); filter1 = new IntentFilter();
filter1.addAction(ACTION1);
filter1.addAction(ACTION2); } @Override
protected void onResume() {
super.onResume();
registerReceiver(receive, filter1);
} @Override
protected void onPause() {
super.onPause();
unregisterReceiver(receive);
} private class Receive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}
}

打印结果如下:

从结果来看,只有粘性广播才能接收到广播信息。

粘性广播特点:

1.需要在AndroidManifest.xml中添加权限

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

2.粘性广播发送除了调用方法不同sendStickyBroadcast(intent1),其他都一样。

3.一般广播都是先注册广播,才能接收到广播,而粘性广播可以做到先发送广播,哪里需要接收该广播就哪里注册,可以后注册广播拿到广播的结果。这就是 普通广播和粘性广播的区别。从示例中也看出了普通广播在跳转到ReceiveActivity中是接受不到广播发送者发出的广播的,只有粘性广播才能接收到。

有人会奇怪,平时也没看到哪里使用粘性广播??其实我也是看到Android 系统中 监测电池电量部分发现的。贴上代码如下:

// Register for the battery changed event
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); / Intent is sticky so using null as receiver works fine
// return value contains the status
Intent batteryStatus = this.registerReceiver(null, filter); // Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL; boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL; // How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

广播的生命周期:

当广播接收者接收到广播调用完onReceive()方法之后,广播的生命周期就结束了。

因此广播接收器不能执行超过10s耗时任务,也不能在onReceive()方法中创建Thread 来执行耗时任务,你可以开启一个Service来执行后台耗时任务,具体可以参考Android 四大组件之Service 的生命周期和使用。

广播的大概原理:

广播是怎么发送的?又是怎么接收的?

我们知道,只有先注册了某个广播之后,广播接收者才能收到该广播。广播注册的一个行为是将自己感兴趣的IntentFilter注册到Android系统的AMS(ActivityManagerService)中,里面保存了一个IntentFilter列表。广播发送者将自己的IntentFilter 的action行为发送到AMS中,然后遍历AMS中的IntentFilter列表,看谁订阅了该广播,然后将消息遍历发送到注册了相应IntentFilter的Activity或者Service中-----也就是会调用抽象方法onReceive()方法。其中AMS起到了中间桥梁作用。

系统广播:

Android系统中有很多系统广播,比如:

Event	Description
Intent.ACTION_BOOT_COMPLETED Boot completed. Requires the android.permission.RECEIVE_BOOT_COMPLETEDpermission.
Intent.ACTION_POWER_CONNECTED Power got connected to the device.
Intent.ACTION_POWER_DISCONNECTED Power got disconnected to the device.
Intent.ACTION_BATTERY_LOW Triggered on low battery. Typically used to reduce activities in your app which consume power.
Intent.ACTION_BATTERY_OKAY Battery status good again.

系统广播具体怎么用?网络上一搜一大把,这里就不讲了。和我们写的广播使用都差不多。

[Android基础]Android四大组件之BroadCast的更多相关文章

  1. Android 基础 (四大组件,五大存储,六大布局)

    Android四大组件: 参考:https://blog.csdn.net/shenggaofei/article/details/52450668 Android四大组件分别为activity.se ...

  2. Android 基础 二 四大组件 Activity

    Activity Intent IntentFilter 一理论概述 一. Activity 用来提供一个能让用户操作并与之交互的界面. 1.1 启动 startActivity(Intent int ...

  3. Android笔记(六十)Android总结:四大组件——BroadcastReceiver篇

    什么是BroadcastReceiver BroadcastReceiver是Android体系的四大组件之一,本质上是一种全局的监听器,用于监听系统全局的广播消息,正式因为其本质为全局监听,因此可以 ...

  4. 【Android】安卓四大组件之Activity(二)

    [Android]安卓四大组件之Activity(二) 前言 在这篇文章之前,我已经写过了一篇有关Activity的内容,是关于activity之间的页面跳转和数据传递,而这篇文章着重强调的是Acti ...

  5. 详解Android中的四大组件之一:Activity详解

    activity的生命周期 activity的四种状态 running:正在运行,处于活动状态,用户可以点击屏幕,是将activity处于栈顶的状态. paused:暂停,处于失去焦点的时候,处于pa ...

  6. 【Android】安卓四大组件之Activity(一)

    [Android]安卓四大组件之Activity(一) 前言 Activity是Android学习中的一个重要组件,想要对其进行系统的了解可以分为几块内容,这一大章节的内容是有关于activity之间 ...

  7. 【Android】安卓四大组件之内容提供者

    [Android]安卓四大组件之内容提供者 1.关于内容提供者 1.1 什么是内容提供者 内容提供者就是contentProvider,作用有如下: 给多个应用提供数据 类似一个接口 可以和多个应用分 ...

  8. 第九章:四大组件之Broadcast Receiver

    第九章:四大组件之Broadcast Receiver   一.广播的功能和特征 广播的生命周期很短,经过调用对象-->实现onReceive-->结束,整个过程就结束了.从实现的复杂度和 ...

  9. android四大组件之Broadcast

    广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...

随机推荐

  1. Mysql转换表存储引擎的三种方式

    或许会有一些场景需要改变表的存储引擎,例如存储日志的表如果几乎只有insert和少量的select操作,为了追求更好的插入性能有可能会需要把存储引擎更换为MyISAM.但是,本文不建议在同一个数据库中 ...

  2. 2048聚合版开源代码,cocos2d-js编写,基于CocosEditor开发工具,可运行Android,ios,html5等

    1. [代码][JavaScript]代码         /** * @GameName : * 2048 * * @DevelopTool: * Cocos2d-x Editor (CocosEd ...

  3. 理解多线程中的ManualResetEvent(C#)

    线程是程序中的控制流程的封装.你可能已经习惯于写单线程程序,也就是,程序在它们的代码中一次只在一条路中执行.如果你多弄几个线程的话,代码运行可能会更加“同步”.在一个有着多线程的典型进程中,零个或更多 ...

  4. Unix环境编程之文件IO

    1.文件IO 2.文件与目录 3.进程 4.多线程编程 5.信号 6.进程间通信 学习linux编程,首先要学会使用shell,这里一些基础命令就不介绍了.这里唯一要提的一个shell命令就是man. ...

  5. BZOJ-3881:Divljak (AC自动机+DFS序+树链求并+树状数组)

    Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. “2 x” ...

  6. java面试题07

    1.重载和重写的区别? 重载(Overload):(1)方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型.重载Overloading是一个类中多态性 ...

  7. 【Matlab】常用函数

    1.取整函数 ceil(x)返回不小于x的最小整数值.floor(x)返回不大于x的最大整数值.round(x)返回x的四舍五入整数值.

  8. MQTT 客户端源码分析

    参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 一.目录结构 首先我们还是来看一下 mosquitto-1.4.14 ...

  9. caffe solver

    caffe solver https://groups.google.com/forum/#!topic/caffe-users/mUIi42aKWHQ https://github.com/BVLC ...

  10. Oracle内置函数大全(转)

    SQL中的单记录函数 1.ASCII 返回与指定的字符对应的十进制数;SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ...