Android四大组件之BroadcastReceiver

本文详细介绍了Android广播机制的使用方法,包括发送广播、接收广播、广播的种类及特性,以及如何验证不同类型的广播行为。通过实例演示了如何在主页面中动态注册广播并进行测试。

Broadcast(广播)是一种广泛运用在应用程序之间传输信息的机制。

BroadcastReceiver(广播接收者)是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用中的广播。

用途:当开机完成后系统会产生一条广播,当网络状态改变时系统会产生一条广播,当电池电量改变时,系统会产生一条广播等。

作为开发者,只需要掌握BroadcastReceiver即可。一般处理Service与Activity之间的消息传递。

使用方法:
1、发送
把信息装入一个Intent对象(如Action、Category)
通过调用相应的方法将Intent对象以广播的方式发送出去
sendBroadcast()
sendOrderBroadcast()
sendStickyBroadcast()
2、接收
当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver的时候,都要实现onReceive()方法。
注意:BroadcastReceiver需要注册(静态注册:在AndroidMainfest.xml中注册、代码注册:在Java类中注册)

BroadcastReceiver的使用注意事项:
1、BroadcastReceiver的生命周期只有十秒左右
2、在BroadcastReceiver里不能做一些比较耗时的操作
3、如果有耗时操作,应该通过发送Intent给Service,有Service来完成
4、不能使用子线程,因为子线程可能还没有完成任务,BroadcastReceiver就已经结束,这是子线程也会被杀掉

广播种类(前两种比较常用)
1、普通广播(Normal broadcasts):所有监听该广播的广播接收者都可以监听到该广播。
2、有序广播(Ordered broadcasts):按照接收者的优先级顺序接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大,优先级越高。可以终止广播意图的继续传播。接收者可以篡改内容。
3、异步广播(粘滞性滞留广播):不能将处理结果传给下一个接收者,无法终止广播,即广播始终存在。
普通广播特点
1、同级别接收先后是随机的(无序)
2、级别低的后收到广播
3、接收器不能截断广播的继续传播,也不能处理广播
4、同级别动态注册高于静态注册
有序广播特点
1、同级别接收先后是随机的
2、能截断广播的继续传播,高级别的广播接收器收到该广播后,可以决定把该广播是否截断。
3、接收器能截断广播的继续传播,也能处理广播
4、同级别动态注册高于静态注册

广播使用实例:

普通广播

1、布局文件中添加发送广播按钮

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:onClick="doClick"
        android:text="发送一条普通广播" />

</RelativeLayout>
2、使用Java代码实现点击按钮发送广播功能

package com.cx.broadcastreceiver;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void doClick(View v){
		switch (v.getId()) {
		case R.id.button1://发送普通广播
			Intent intent = new Intent();
			intent.putExtra("msg", "这是一条普通广播");
			//为了过滤广播设置Action,唯一的
			intent.setAction("cx_one");
			sendBroadcast(intent);
			break;
		}
	}
}
3、定义一个广播接收类,并打印广播信息
package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/*
 * 接收广播
 */
public class MyBroadcastReceiver1 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("11111111111111111", s);
	}
}
4、在AndroidMainfest.xml中注册广播
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cx.broadcastreceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.cx.broadcastreceiver.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>
        
        <receiver android:name="com.cx.broadcastreceiver.MyBroadcastReceiver1">
           <!--  添加过滤器 ,与发送广播设置的Action相同-->
           <!-- 接收系统广播时,只需匹配系统Action就可以了 -->
            <intent-filter >
                <action android:name="cx_one"/>
            </intent-filter>
        </receiver>
        
    </application>
</manifest>
这样,我们就完成了广播的发送与接收,运行程序点击发送按钮,就会看到打印广播信息
为了验证普通广播的无序特点

1、我们增加一个广播接收类MyBroadcastReceiver2

package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/*
 * 接收广播
 */
public class MyBroadcastReceiver2 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("2222222222222222", s);
	}
}
2、在AndroidMainfest.xml中添加MyBroadcastReceiver2的注册
<receiver android:name="com.cx.broadcastreceiver.MyBroadcastReceiver2">
      <intent-filter >
           <action android:name="cx_one"/>
      </intent-filter>
</receiver>
运行程序查看消息打印时间,正常情况下时间是相同的。但是我在测试的时候出现,MyBroadcastReceiver1先打印,MyBroadcastReceiver2后打印,时间相差3~4ms。

下面在以上代码的基础上,验证级别低的后收到广播特点

1、在AndroidMainfest.xml中设置广播级别

<pre name="code" class="html"><receiver android:name="com.cx.broadcastreceiver.MyBroadcastReceiver1">
   <!--  添加过滤器 ,与发送广播设置的Action相同-->
   <!-- 接收系统广播时,只需匹配系统Action就可以了 -->
    <intent-filter 
        android:priority="100">
        <action android:name="cx_one"/>
    </intent-filter>
</receiver>

<receiver android:name="com.cx.broadcastreceiver.MyBroadcastReceiver2">
    <intent-filter 
        android:priority="200">
        <action android:name="cx_one"/>
    </intent-filter>
</receiver>

 这里将MyBroadcastReceiver1的优先级设置为100,MyBroadcastReceiver2的优先级设置为200,所以会出现MyBroadcastReceiver2广播信息先打印。在测试时如果将优先级设置相同,会出现MyBroadcastReceiver1先打印,MyBroadcastReceiver2后打印,时间相差3~4ms。

接下来我们验证普通广播接收器不能截断广播的特点

1、在设置优先级MyBroadcastReceiver2大于MyBroadcastReceiver1的情况下,在MyBroadcastReceiver2中添加广播截断代码

package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/*
 * 接收广播
 */
public class MyBroadcastReceiver2 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("2222222222222222", s);
//		//截断广播测试
		abortBroadcast();
	}
}
运行程序,打印MyBroadcastReceiver2中广播信息后,会打印报错代码,接着打印MyBroadcastReceiver1中的广播信息。

验证普通广播接收器不能处理广播的特点

1、在设置优先级MyBroadcastReceiver2大于MyBroadcastReceiver1的情况下,在MyBroadcastReceiver2中添加数据处理代码

package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/*
 * 接收广播
 */
public class MyBroadcastReceiver2 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("2222222222222222", s);
		
		//数据处理
		Bundle bundle = new Bundle();
		bundle.putString("test", "处理的数据");
		setResultExtras(bundle);
	}
}
2、在MyBroadcastReceiver1中增加数据接收代码

package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/*
 * 接收广播
 */
public class MyBroadcastReceiver1 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("11111111111111", s);
		
		//广播处理代码接收
		Bundle bundle = getResultExtras(true);
		String s2 = bundle.getString("test");
		Log.e("22222221111111", "结果是:" + s2);
	}
}
运行程序,打印MyBroadcastReceiver2中广播信息后,会打印报错代码,接着打印MyBroadcastReceiver1中的广播信息,广播处理信息为空
验证同级别动态注册高于静态注册特点

1、将MyBroadcastReceiver2在AndroidMainfest.xml中的注册信息删除,并在主页面中增加MyBroadcastReceiver2的注册信息

package com.cx.broadcastreceiver;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//动态注册MyBroadcastReceiver2
		IntentFilter intentFilter = new IntentFilter("cx_one");
		MyBroadcastReceiver2 myBroadcastReceiver = new MyBroadcastReceiver2();
		registerReceiver(myBroadcastReceiver, intentFilter);
	}

	public void doClick(View v){
		switch (v.getId()) {
		case R.id.button1://发送普通广播
			Intent intent = new Intent();
			intent.putExtra("msg", "这是一条普通广播");
			//为了过滤广播设置Action,唯一的
			intent.setAction("cx_one");
			sendBroadcast(intent);
			break;
		}
	}
}
运行程序会发现MyBroadcastReceiver2先打印。动态注册缺点,如果注册类生命周期结束,该广播接收器也将收不到广播。

有序广播

1、布局文件中增加有关有序广播按钮

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:onClick="doClick"
        android:text="发送一条普通广播" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="48dp"
        android:onClick="doClick"
        android:text="发送一条有序广播" />

</RelativeLayout>
2、Java代码中增加有序广播按钮点击事件

package com.cx.broadcastreceiver;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//动态注册MyBroadcastReceiver2
		IntentFilter intentFilter = new IntentFilter("cx_one");
		MyBroadcastReceiver2 myBroadcastReceiver = new MyBroadcastReceiver2();
		registerReceiver(myBroadcastReceiver, intentFilter);
	}

	public void doClick(View v){
		switch (v.getId()) {
		case R.id.button1://发送普通广播
			Intent intent = new Intent();
			intent.putExtra("msg", "这是一条普通广播");
			//为了过滤广播设置Action,唯一的
			intent.setAction("cx_one");
			sendBroadcast(intent);
			break;
			
		case R.id.button2://发送普通广播
			Intent intent2 = new Intent();
			intent2.putExtra("msg", "这是一条有序广播");
			//为了过滤广播设置Action,唯一的
			intent2.setAction("cx_one");
			//这里权限设为null
			sendOrderedBroadcast(intent2, null);
			break;
		}
	}
}
3、重复普通广播中的测试,发现能够实现截断广播和处理广播。
异步广播

1、布局文件中增加异步广播按钮

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:onClick="doClick"
        android:text="发送一条普通广播" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="48dp"
        android:onClick="doClick"
        android:text="发送一条有序广播" />
    
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="96dp"
        android:onClick="doClick"
        android:text="发送一条异步广播" />

</RelativeLayout>
2、增加一个广播接收类MyBroadcastReceiver3

package com.cx.broadcastreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyBroadcastReceiver3 extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String s = intent.getStringExtra("msg");
		Log.e("3333333333333333", s);
	}
}

3、Java代码中增加异步广播按钮点击事件

package com.cx.broadcastreceiver;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//动态注册MyBroadcastReceiver2
		IntentFilter intentFilter = new IntentFilter("cx_one");
		MyBroadcastReceiver2 myBroadcastReceiver = new MyBroadcastReceiver2();
		registerReceiver(myBroadcastReceiver, intentFilter);
	}

	public void doClick(View v){
		switch (v.getId()) {
		case R.id.button1://发送普通广播
			Intent intent = new Intent();
			intent.putExtra("msg", "这是一条普通广播");
			//为了过滤广播设置Action,唯一的
			intent.setAction("cx_one");
			sendBroadcast(intent);
			break;
			
		case R.id.button2://发送有序广播
			Intent intent2 = new Intent();
			intent2.putExtra("msg", "这是一条有序广播");
			//为了过滤广播设置Action,唯一的
			intent2.setAction("cx_one");
			//这里权限设为null
			sendOrderedBroadcast(intent2, null);
			break;
			
		case R.id.button3://发送异步广播
			Intent intent3 = new Intent();
			intent3.putExtra("msg", "这是一条异步广播");
			//为了过滤广播设置Action,唯一的
			intent3.setAction("cx_three");
			sendStickyBroadcast(intent3);
			
			//前两种广播必须是先注册,后发送。这里先发送,后注册
			IntentFilter intentFilter = new IntentFilter("cx_three");
			MyBroadcastReceiver3 myBroadcastReceiver = new MyBroadcastReceiver3();
			registerReceiver(myBroadcastReceiver, intentFilter);
			break;
		}
	}
}
4、增加异步广播需要权限
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
注意:对于上面的所有代码,凡是在主页面中动态注册广播的,都要在页面结束时销毁广播。不好意思上面的忘记写了。

@Override
protected void onDestroy() {
	// TODO Auto-generated method stub
	super.onDestroy();
	unregisterReceiver(myBroadcastReceiver2);
	unregisterReceiver(myBroadcastReceiver3);
}
源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c小旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值