四大组件之BroadcastReceiver(一)

本文详细介绍了Android中的广播机制,包括标准广播、有序广播、本地广播的使用方法及发送自定义广播的示例。重点阐述了如何注册和接收不同类型的广播,以及在实际应用中的灵活运用。

diligence is your life password, can translate your grand epic poem.勤奋是你生命的密码,能译出你一部壮丽的诗。


 本讲内容: Broadcast Receiver 广播接收者的使用 


一、Broadcast Receiver的介绍

记得我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就会播放一条广播来告知全校的师生。譬如:当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。


二、Android中的广播分为两种类型:标准广播和有序广播。

1、标准广播是是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。

2、有序广播则是一种同步执行的广播,在广播发出之后,同一时刻只会一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。


三、注册广播的方式有两种,在代码中注册和在AndroidManifest.xml中注册,其中前者称为动态注册,后者称为静态注册。


四、如何创建一个广播接收器?

只需要新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceive()方法,这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。


示例一:接收系统广播(譬如:动态注册实现网络变化)

  

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	private IntentFilter intentFilter;
	private NetworkChangeReceiver networkChangeReceiver;

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

		intentFilter = new IntentFilter();
		// 添加一个值为android.net.conn.CONNECTIVITY_CHANGE的action,因为当网络状态发生变化时,系统会发出一条值为
		// android.net.conn.CONNECTIVITY_CHANGE的广播。即我们的广播接收器想要监听什么广播,就在这里添加相应的action就行了。
		intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
		// 创建一个广播接收器
		networkChangeReceiver = new NetworkChangeReceiver();
		// 动态注册
		registerReceiver(networkChangeReceiver, intentFilter);
	}

	protected void onDestroy() {
		super.onDestroy();
		// 取消注册
		unregisterReceiver(networkChangeReceiver);
	}

	class NetworkChangeReceiver extends BroadcastReceiver {
		public void onReceive(Context context, Intent intent) {
			//ConnectivityManager主要管理和网络连接相关的操作,然后通过它的getNetworkInfo()方法得到NetworkInfo实例,
			//NetworkInfo类包含了对wifi和mobile两种网络模式连接的
			ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mobileInfo = connectionManager.getNetworkInfo(connectionManager.TYPE_MOBILE);
			NetworkInfo wifiInfo = connectionManager.getNetworkInfo(connectionManager.TYPE_WIFI);

			if (mobileInfo.isConnected()||wifiInfo.isConnected()) {
				Toast.makeText(context, "WIFI或GPRS网络已连接", Toast.LENGTH_LONG).show();
			}else{
				Toast.makeText(context, "网络没有连接", Toast.LENGTH_LONG).show();
				// 跳转到无线网络设置界面    
				//startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));    
				// 跳转到无限wifi网络设置界面    
				//startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS));  
			}

		}
	}

}

在AndroidManifest.xml中注册(查询系统的网络状态就要声明权限)

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



示例二:接收系统广播(譬如:静态注册实现开机启动)

动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存在一个缺点,即必须要在程序启动后才能接收到广播,因为注册的逻辑是写在onCreate()方法中的。


重启开机会执行onReceive()方法

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
}


这里不再使用内部类的方式来定义广播接收器,因为需要在AndroidManifest.xml中将这个广播接收器注册。

下面是BootCompleteReceiver.java文件:

public class BootCompleteReceiver extends BroadcastReceiver{
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();		
	}
}


在AndroidManifest.xml文件(要声明监听系统开机广播权限)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcastreceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <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>
        
        <receiver android:name=".BootCompleteReceiver">
            <intent-filter >
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>


五、发送自定义广播(之前我们学习了通过广播接收器接收系统广播)
示例三:(发送标准广播)


下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		Button button=(Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				//自定义广播,这样所有监听com.example.broadcastreceiver.MY_BROADCAT这条广播的广播接收器就会收到消息
				Intent intent=new Intent("com.example.broadcastreceiver.MY_BROADCAT");
				sendBroadcast(intent);
			}
		});
	}

}

下面是MyBroadcastReceiver.java文件:

public class MyBroadcastReceiver extends BroadcastReceiver {
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "received in MyBroadcastReceived",Toast.LENGTH_LONG).show();
	}
}
下面是AndroidManifest.xml文件

 <receiver android:name=".MyBroadcastReceiver" >
            <intent-filter>
                <action android:name="com.example.broadcastreceiver.MY_BROADCAT" />
            </intent-filter>
</receiver>


示例四:(发送标准广播)

广播是一种可以跨进程的通信方式,从接收系统广播可以看出来,因此在我们应用程序内发出的广播,其它的应用程序也可以收到的。

  

新建一个新的项目,在这个项目定义一个广播AnotherBroadcastReceiver

下面是AnotherBroadcastReceiver.java文件:

public class AnotherBroadcastReceiver extends BroadcastReceiver{
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "received in AnotherBroadcastReceiver", Toast.LENGTH_LONG).show();
	}
}
下面是AndroidManifest.xml文件

<receiver android:name=".AnotherBroadcastReceiver" >
            <intent-filter>
                <action android:name="com.example.broadcastreceiver.MY_BROADCAT" />
            </intent-filter>
</receiver>


示例五:(有序广播)

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		Button button=(Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				//自定义广播,这样所有监听com.example.broadcastreceiver.MY_BROADCAT这条广播的广播接收器就会收到消息
				Intent intent=new Intent("com.example.broadcastreceiver.MY_BROADCAT");
				//有序广播两个参数,第二个参数是一个权限相关的字符串,传入null就行了
				sendOrderedBroadcast(intent, null);
			}
		});
	}

}

注意:使用sendOrderedBroadcast方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。


下面是AndroidManifest.xml文件

<receiver android:name=".MyBroadcastReceiver" >
            <intent-filter android:priority="100">
                <action android:name="com.example.broadcastreceiver.MY_BROADCAT" />
            </intent-filter>
</receiver>
android:priority 属性给广播接收器设置优先级,这里设置为100,以保证它一定会在AnotherBroadcastReceiver之前收到广播。

下面是MyBroadcastReceiver.java文件:

public class MyBroadcastReceiver extends BroadcastReceiver {
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "receiver in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
		//将这条广播截断,后面的广播接收器将无法收到
		abortBroadcast();
	}
}


示例六:使用本地广播

前面我们发送和接收的广播全部都属于系统全局广播,即发出的广播可以被其它任务应用程序接收到,并且我们也可以接收任何应用程序的广播。这样很容易引起安全性问题,譬如其它程序不断地向我们的广播接收器发送各种垃圾广播。为了解决广播的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播也只能接收来自本应用程序发出的广播。

本地广播使用了一个LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法。


下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	private IntentFilter intentFilter;
	private LocalBroadcastReceiver localReceiver;
	private LocalBroadcastManager localBroadcastManager;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		//获取实例
		localBroadcastManager=LocalBroadcastManager.getInstance(this);
		
		Button button=(Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				//自定义广播,这样所有监听com.example.broadcastreceiver.LOCAL_BROADCAT这条广播的广播接收器就会收到消息
				Intent intent=new Intent("com.example.broadcastreceiver.LOCAL_BROADCAST");
				//发送本地广播
				localBroadcastManager.sendBroadcast(intent);
			}
		});
		
		//注册广播
		intentFilter=new IntentFilter();
		intentFilter.addAction("com.example.broadcastreceiver.LOCAL_BROADCAST");
		localReceiver=new LocalBroadcastReceiver();
		localBroadcastManager.registerReceiver(localReceiver, intentFilter);
	}
	
	protected void onDestroy() {
		super.onDestroy();
		localBroadcastManager.unregisterReceiver(localReceiver);
	}
	
	class LocalBroadcastReceiver extends BroadcastReceiver{
		public void onReceive(Context context, Intent intent) {
			Toast.makeText(context, "receiver local Broadcast", Toast.LENGTH_LONG).show();
		}
	}

}
可以尝试示例四中其它应用程序无法收到这条com.example.broadcastreceiver.LOCAL_BROADCAST广播

注意:本地广播是无法通过静态注册的方式来接收的,因为静态注册主要就是为了让程序在未启动的情况下也能收到广播,而发送本地广播时,我们的程序肯定是已经启动了。



Take your time and enjoy it 要原码的、路过的、学习过的请留个言,顶个呗~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值