现在的位置: 首页 > 综合 > 正文

android BroadCasetReceiver讲解

2014年09月05日 ⁄ 综合 ⁄ 共 14501字 ⁄ 字号 评论关闭

简介:

BroadcastReceiver: 广播接收器,一个专门接收广播的东东,它需要在系统中进行注册,注册方式有静态注册(在manifest.xml中注册)和动态注册(在Activity或service中注册)两种, 注册的作用就是告诉系统,我只接收什么样的广播(具体通过action属性设置),如果有这样的广播,就叫我一声,我来处理下。


静态注册:在manifest.xml中进行注册,表示只要是android.intent.action.mybroadcast_action这个地址的广播,MyBroadcastReceiverS1都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyBroadcastReceiverS1也会被系统调用而自动运行。

<!-- 在manifest。xml中注册广播接收者 -->
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.mybroadcast_action" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>


动态注册:在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期,当Activity或service销毁时,我们必须对Receiver解除注册,否则会报异常,因此我们要在特定的方法中对Receiver进行解除注册。

//在Activity中动态的注册广播接收器
battertChangeReceiver = new MyBroadcastReceiverD4();
		IntentFilter filter = new IntentFilter(
				"android.intent.action.MY_BROADCAST");
		registerReceiver(battertChangeReceiver, filter);
	
//在Activity的destroy方法解除注册
@Override
protected void onDestroy() {
	super.onDestroy();
	unregisterReceiver(battertChangeReceiver);
}

如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。

普通广播:对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。

有序广播:有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。静态注册的有序广播要加上android:priority="1000"属性来定义优先级,动态的可以在代码中设置setPriority();发送有序广播调用方法sendOrderedBroadcast(Intent intent,String permission);

<!-- 在manifest。xml中注册广播接收者,有序广播需要指定priority属性,同时注意,一个接收器可以注册多种类型的广播,如下面定义的MyBroadcastReceiverS3 -->
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.mybroadcast_action" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS2" >
            <intent-filter android:priority="999" >
                <action android:name="android.intent.action.mybroadcast_action" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
		<!--定义两个action,该Receiver可以接收多种类型的广播 -->
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS3" >
            <intent-filter android:priority="998" >
                <action android:name="android.intent.action.mybroadcast_action" />
				<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

在发送的有序广播的前提下,在广播的Receiver方法里面调用setResultExtras(bundle),那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者,非有序广播即使设置了也无效。

//如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@MyBroadcastReceiverS2");
		setResultExtras(bundle);

调用abortBroadcast()可以停止广播的传播,此方法只对有序广播有效,普通广播无效。高优先级的Receiver调用该方法之后,低优先级的Receiver将不会接收到广播。

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

			case R.id.button2:// 有序广播
			intent = new Intent("android.intent.action.mybroadcast_action");
			intent.putExtra("type", 2);
			intent.putExtra("msg", "发送有序广播 ");
			//发送有序广播
			sendOrderedBroadcast(intent,"scott.permission.mybroadcast_permission");
			break;

所以我们在AndroidMainfest.xml中定义一个权限(关于权限定义,声明与使用,请参照:http://blog.csdn.net/liuhe688/article/details/6417983),然后使用该权限:

 <!-- 自定义权限 -->
    <permission
        android:name="scott.permission.mybroadcast_permission"
        android:protectionLevel="normal" >
    </permission>

    <!-- 使用自定义的权限 -->
    <uses-permission android:name="scott.permission.mybroadcast_permission" /> 

以下是我做的project,实现静态注册,动态注册等功能。

1. 静态注册的MyBroadcastReceiverS1

package com.androidstudydemo.broadcastReceiver;

import com.androidstudydemo.common.util.DisPlayUtil;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.sax.StartElementListener;
import android.util.Log;
import android.widget.TextView;

/**
 * broadcastreceiver注册有两种方法,一种静态注册,一种动态注册,此对象采用静态注册,即 在manifest.xml文件中进行注册。
 * 
 * @author zkx016
 * 
 */
public class MyBroadcastReceiverS1 extends BroadcastReceiver {

	String TAG = "MyBroadcastReceiverS1";

	@Override
	public void onReceive(Context arg0, Intent arg1) {
		int type = arg1.getIntExtra("type", 1);
		String msg = arg1.getStringExtra("msg");
		msg += getResultExtras(true).getString("msg");

		Log.i(TAG, "MyBroadcastReceiverS1:" + type + "/" + msg);

		String info = TAG + "==>  action is:" + arg1.getAction()
				+ "  message is:" + msg;
		DisPlayUtil.ShowToastMessage(arg0, info);

		Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
		Message message = handler.obtainMessage();
		message.what = 1;
		message.obj = info;
		message.sendToTarget();

		// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者,若是普通广播,下面的请直接忽略
		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@MyBroadcastReceiverS1");
		setResultExtras(bundle);
	}

}

2.静态注册的MyBroadcastReceiverS2.java

package com.androidstudydemo.broadcastReceiver;

import com.androidstudydemo.common.util.DisPlayUtil;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class MyBroadcastReceiverS2 extends BroadcastReceiver {

	String TAG = "MyBroadcastReceiverS2";

	@Override
	public void onReceive(Context arg0, Intent arg1) {
		int type = arg1.getIntExtra("type", 1);
		String msg = arg1.getStringExtra("msg");
		Bundle bundle1 = getResultExtras(true);
		msg += bundle1.getString("msg");

		Log.i(TAG, msg);

		String info = TAG + "==>  action is:" + arg1.getAction()
				+ "  message is:" + msg;
		DisPlayUtil.ShowToastMessage(arg0, info);

		Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
		Message message = handler.obtainMessage();
		message.what = 1;
		message.obj = info;
		message.sendToTarget();

		// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@MyBroadcastReceiverS2");
		setResultExtras(bundle);
		abortBroadcast();//终止广播的继续传播,可以看见,broadCastReceiverS3没有接收到广播

	}

}

3.静态注册的MyBroadcastReceiverS3 

package com.androidstudydemo.broadcastReceiver;

import com.androidstudydemo.common.util.DisPlayUtil;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

public class MyBroadcastReceiverS3 extends BroadcastReceiver {

	String TAG = "MyBroadcastReceiverS3";

	@Override
	public void onReceive(Context arg0, Intent arg1) {
		int type = arg1.getIntExtra("type", 1);
		String msg = arg1.getStringExtra("msg");
		msg += getResultExtras(true).getString("msg");
		Log.i(TAG, msg);

		String info = TAG + "==>  action is:" + arg1.getAction()
				+ "  message is:" + msg;
		DisPlayUtil.ShowToastMessage(arg0, info);

		Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
		Message message = handler.obtainMessage();
		message.what = 1;
		message.obj = info;
		message.sendToTarget();

		// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@MyBroadcastReceiverS3");
		setResultExtras(bundle);

		//当网络可用发生变化时,系统会发出一个广播,所以我们在断开网络或重启网络时不用我们自己手动的发一个广播。
		if (!isNetworkAvailable(arg0)) {  
            Toast.makeText(arg0, "network disconnected!", 0).show();  
        }  
	}
	
	 /** 
     * 网络是否可用 
     *  
     * @param context 
     * @return 
     */  
    public static boolean isNetworkAvailable(Context context) {  
        ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);  
        NetworkInfo[] info = mgr.getAllNetworkInfo();  
        if (info != null) {  
            for (int i = 0; i < info.length; i++) {  
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  

}

4.动态注册的MyBroadcastReceiverD4.java,在BatteryChangeActivity中动态注册,一进入页面即提示当前电量。

package com.androidstudydemo.broadcastReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;

public class MyBroadcastReceiverD4 extends BroadcastReceiver {

	String TAG = "MyBroadcastReceiverD4";

	@Override
	public void onReceive(Context arg0, Intent intent) {

		int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); // 当前电量
		int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1); // 总电量
		int percent = currLevel * 100 / total;
		Toast.makeText(arg0, "当前电量:" + percent, 0).show();

		Log.i(TAG, "battery: " + percent + "%");
	}

}

5.主界面MyBroadcastSenderActivity,里面包含三个按钮:发送普通广播,发送有序广播,动态注册示例 三个按钮。

package com.androidstudydemo.broadcastReceiver;

import java.util.HashMap;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.androidstudydemo.common.BaseActivity;
import com.androidstudydemo.common.MyTitleView;
import com.androidstudydemo.common.R;
import com.androidstudydemo.common.util.DisPlayUtil;

public class MyBroadcastSenderActivity extends BaseActivity implements
		OnClickListener {

	static TextView textView = null;
	MyTitleView title = null;
	// MyBroadcastReceiver1 receiver1; receiver1通过在manifest。xml中进行注册
	MyBroadcastReceiverS2 receiver2;// 在代码中动态注册。
	int i = 1;

	static Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 1:
				if (textView != null) {
					String info = (String) msg.obj;
					textView.append(info);
				}
				break;

			default:
				break;
			}
		};
	};

	public static Handler getHandler() {
		return handler;
	}

	@Override
	protected void onStart() {
		super.onStart();
		// 静态注册,一般是在onstart方法进行注册,在onstop方法进行销毁
		receiver2 = new MyBroadcastReceiverS2();
		IntentFilter filter2 = new IntentFilter();
		filter2.addAction("myaction");
		registerReceiver(receiver2, filter2);
	}

	@Override
	protected void onStop() {
		super.onStop();
		if (receiver2 != null) {// 动态注册,在activity销毁时要解除注册,否则会报错。
			unregisterReceiver(receiver2);
		}
	}

	public void initTitle(MyTitleView title) {
		HashMap<String, Object> datas = new HashMap<String, Object>();
		datas.put("title", R.string.broadcastReceiver_title);
		datas.put("instration", R.string.broadcastReceiver_isntration);
		title.setInitDatas(datas);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_mybroadcastsenderdemo);
		textView = (TextView) this.findViewById(R.id.textView1);
		title = (MyTitleView) this.findViewById(R.id.title);
		initTitle(title);
	}

	public void initInstration() {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("title", "broadcastReceiver讲解");
		map.put("message",
				getResources().getString(R.string.broadcastReceiver_isntration));
		DisPlayUtil.showAlertDialog(MyBroadcastSenderActivity.this, map);
	}

	@Override
	public void onClick(View arg0) {
		Intent intent;
		switch (arg0.getId()) {
		case R.id.button1:// 普通广播
			intent = new Intent("android.intent.action.mybroadcast_action");
			intent.putExtra("type", 1);
			intent.putExtra("msg", "发送普通广播 ");
			sendBroadcast(intent);
			break;
		case R.id.button2:// 有序广播
			intent = new Intent("android.intent.action.mybroadcast_action");
			intent.putExtra("type", 2);
			intent.putExtra("msg", "发送有序广播 ");
			sendOrderedBroadcast(intent,"scott.permission.mybroadcast_permission");
			break;
		case R.id.button3:
			intent = new Intent(this, BatteryChangeActivity.class);
			startActivity(intent);
			break;
		case R.id.button4:
			break;
		default:
			break;
		}

	}
}

6.用于动态注册的BatteryChangeActivity

package com.androidstudydemo.broadcastReceiver;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import com.androidstudydemo.common.BaseActivity;

public class BatteryChangeActivity extends BaseActivity {

	MyBroadcastReceiverD4 battertChangeReceiver;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		battertChangeReceiver = new MyBroadcastReceiverD4();
		IntentFilter filter = new IntentFilter(
				"android.intent.action.MY_BROADCAST");
		registerReceiver(battertChangeReceiver, filter);
		
		Intent batteryIntent = new Intent("android.intent.action.MY_BROADCAST");  
		sendBroadcast(batteryIntent);
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unregisterReceiver(battertChangeReceiver);
	}
}

7. 静态注册和权限配置manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- android:installLocation="auto" 自动选择安装位置(sd卡或手机内存) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidstudydemo.common"
    android:installLocation="auto"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <!-- 自定义权限 -->
    <permission
        android:name="scott.permission.mybroadcast_permission"
        android:protectionLevel="normal" >
    </permission>
   
    <!-- 使用自定义的权限 -->
    <uses-permission android:name="scott.permission.mybroadcast_permission" />  
       
    <!-- 使用网络功能所需权限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
       
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <uses-library android:name="android.test.runner" />
       
        <!-- 在manifest.xml中注册广播接收者 -->
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.mybroadcast_action" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS2" >
            <intent-filter android:priority="999" >
                <action android:name="android.intent.action.mybroadcast_action" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS3" >
            <intent-filter android:priority="998" >
                <action android:name="android.intent.action.mybroadcast_action" />
		<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
		
        <activity
            android:name="com.androidstudydemo.main.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>
		<activity
            android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastSenderActivity"
            android:label="@string/app_name" >
        </activity>
		 <activity
            android:name="com.androidstudydemo.broadcastReceiver.BatteryChangeActivity"
            android:label="@string/app_name" >
        </activity>
		
    </application>
</manifest>

抱歉!评论已关闭.