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

Android的四大组件之二–BroadcastReceiver(相关内容,开机启动Service)

2013年08月05日 ⁄ 综合 ⁄ 共 14853字 ⁄ 字号 评论关闭
前面介绍了Service,接着介绍下相对简单的BroadcastReceiver;

Base class for code that will receive intents sent by sendBroadcast(). You can either dynamically register an instance of this class with Context.registerReceiver() or
statically publish an implementation through the <receiver> tag
in your AndroidManifest.xml.
 

(大致的意思:BroadcastReceiver是用于接收通过sendBroadcast()发送的intents。可以通过Context.registerReceiver()动态注册一个实例,或者在AndroidManifest.xml中静态注册)

 

广播接收器只能用于接受广播,对广播的通知做出相应的处理,很多广播是由系统提供的(如电量不足等);

广播接收器同样没有界面,但是他们可以接受到信息后启动activity或者通过notificationManger通知用户(响铃,振动等);

 

广播分为两类:

Normal broadcasts:(通过sendBroadcast()发送),是完全异步的。全部的BroadcastReceiver时没有规定的顺序的接收的,逻辑上,可以在同一时刻所有接收者接收到。消息传递的效率比较高,但缺点是,接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;

Ordered broadcasts :(通过sendOrderBroadcast()发送),广播一次只发送给一个接收者(每次只有一个接收者可以接收,但是不是全部只有一个接收

者);全部的接收者都是有序的,能够传递结果给下一个接收者,或者放弃广播(这样后面的广播接收者都收不到广播)。按照接收者声明的优先级别(声明

intent-filter元素的android:priority属性中,数越大优先级别越高(如果权限值想听则任意顺序),取值范围:-1000到1000。也可以调用IntentFilter对象的

setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存

入数据,当广播传给B时,B可以从广播中得到A存入的数据。

There are two major classes of broadcasts that can be received:

Normal broadcasts (sent with Context.sendBroadcast) are completely asynchronous. All receivers of the broadcast are run in an undefined order, often at the same time. This is more efficient, but means that receivers cannot use the result
or abort APIs included here.

Ordered broadcasts (sent with Context.sendOrderedBroadcast) are delivered to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it
won't be passed to other receivers. The order receivers run in can be controlled with the android:priority attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.

普通广播:异步,数据不共享,传递效率高

有序广播:同步,数据可以达到共享,传递效率低

注意:

如果onResume()中注册了接收者,则必须在onPause()中注销;

不要在onSaveInstanceState中注销,因为如果用户亦如历史堆栈中,这样将不能被called;

 

Reciver的生命周期

广播接收者的对象只有在回调onReceive()这个函数时有效,一旦从这个函数返回,这个对象就被结束,不再激活

在onReceive()中,任何异步的操作都是不可行的。因为需要从onRecive()这个函数回来去处理异步的操作,但是这个广播接收者不再被激活,系统将会在异步操

完成前结束进程。特别是在这里面显示对话框或者绑定service不行,但是可以用其他替代的方式,前者可以notificationManger,后者用startService()发送请求。

 

BroadcastReceiver相关的函数:

Context.sendBroadcast()

   发送的是普通广播,所有订阅者都有机会获得并进行处理。

Context.sendOrderedBroadcast()

   发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播

BroadcastReceiver.abortBroadcast(),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将处理结果存放进

广播Intent,然后传给下一个接收者。


上代码:

结果1:

结果2:

结果3:

结果4:

BroadcastDemoActivity.java

 

package com.potato;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/**
 * Broadcast Receiver:我们可以通过
 * Context.sendBroadcast()
 * Context.sendOrderedBroadcast() 
 * Context.sendStickyBroadcast()
 * 这些方法,传递Intent给感兴趣的广播。
 */
public class BroadcastDemoActivity extends Activity {

	public static final String INTENAL_ACTION_1 = "com.potato.INTENT_ACTION_1";
	public static final String INTENAL_ACTION_2 = "com.potato.INTENT_ACTION_2";
	public static final String INTENAL_ACTION_3 = "com.potato.INTENT_ACTION_3";
	// 权限(蓝牙)
	private static final String BLUETOOTH_PERMISSION = android.Manifest.permission.BLUETOOTH;
	
	private boolean mIsOrderBroadcast = false;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// 静态注册broadcastReceiver(就是在androidMainifest.xml中注册)				// 注1
		Button btnImplictBroadcast = (Button) findViewById(R.id.btn_implict_intent_broadcast);
		btnImplictBroadcast.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				Intent intent = new Intent(INTENAL_ACTION_1).putExtra(
						"person_info", "Potato is so smart!!!");
				// (触发Test1BroadCastReceiver,Test1BroadCastReceiver和动态注册的INTENAL_ACTION_1)
				sendBroadcast(intent);										// 注2
				// 只有在manifest.xml中增加了蓝牙权限才能接收					// 注3
				// sendBroadcast(intent, BLUETOOTH_PERMISSION);
			}

		});

		// 动态注册broadcastReceiver(就是在代码手动注册,不在xml中注册)		// 注4
		Button btnMoveBroadcast = (Button) findViewById(R.id.btn_auto_broadcast);
		btnMoveBroadcast.setOnClickListener(new OnClickListener() {
			// (触发Test1BroadCastReceiver,Test1BroadCastReceiver的INTENAL_ACTION_1)
			@Override
			public void onClick(View v) {
				
				Intent intent = new Intent(INTENAL_ACTION_2);
				// sendBroadcast(intent);
				// 只有在manifest.xml中增加了蓝牙权限才能接受到
				sendBroadcast(intent, BLUETOOTH_PERMISSION);				// 注3
			}

		});

		// 多个broadcast
		Button btnMutilDyanimcalBroadcast = (Button) findViewById(R.id.btn_mutil_auto_broadcast);
		btnMutilDyanimcalBroadcast.setOnClickListener(new OnClickListener() {				// 注5

			@Override
			public void onClick(View v) {
				// 注册多个广播
				IntentFilter filter = new IntentFilter();
				filter.addAction(Intent.ACTION_BATTERY_CHANGED);// 系统电量检测信息
				filter.addAction(INTENAL_ACTION_3);// 第三组自定义消息
				registerReceiver(mBatInfoReceiver, filter);

				Intent intent = new Intent(INTENAL_ACTION_3);
				intent.putExtra("name", "potato");
				// 触发mBatInfoReceiver
				sendBroadcast(intent, BLUETOOTH_PERMISSION);// 只有在manifest.xml中增加了蓝牙权限才能接受到
			}

		});
		
		// 有序的Broadcast
		Button btnOrderBroadcast = (Button) findViewById(R.id.btn_order_broadcast);
		btnOrderBroadcast.setOnClickListener(new OnClickListener() {				// 注7

			@Override
			public void onClick(View v) {

				Intent intent = new Intent();
				intent.setAction(INTENAL_ACTION_1);
				intent.putExtra("person_info", "Potato is so smart!!!");
				// 触发mBatInfoReceiver
				sendOrderedBroadcast(intent, null);// 只有在manifest.xml中增加了蓝牙权限才能接受到
				mIsOrderBroadcast = true;
			}

		});
	}

	// 在onStart中动态注册广播,当然也可以在onCreate里面注册
	@Override
	protected void onStart() {
		super.onStart();
		// 动态注册
		IntentFilter intentFilter = new IntentFilter(INTENAL_ACTION_2);				// 注4
		intentFilter.addAction(INTENAL_ACTION_1);
		intentFilter.setPriority(700);												// 注7
		// 也可以用这种方法动态注册多个,说明我可以”接收“这么多的动态广播。
		/*
		 * IntentFilter intentFilter= new IntentFilter();
		 * intentFilter.addAction("action1"); intentFilter.addAction("action2");
		 */
		registerReceiver(mBroadcastIntent, intentFilter);
	}

	// 在onStop中取消注册广播,如果在onCreate里面注册,那么在onDestroy里面取消注册。
	@Override
	protected void onStop() {
		super.onStop();																// 注4
		unregisterReceiver(mBroadcastIntent);
		unregisterReceiver(mBatInfoReceiver);
	}

	// 接收动态注册广播的BroadcastReceiver
	private BroadcastReceiver mBroadcastIntent = new BroadcastReceiver() {				// 注4
		@Override
		public void onReceive(Context context, Intent intent) {
			// 多个广播
			if (intent.getAction().equals("com.potato.INTENT_ACTION_2")) {
				Log.d("BroadCastReceiver", "mBroadcastIntent----------INTENT_ACTION_2");
			}

			if (intent.getAction().equals("com.potato.INTENT_ACTION_1"))
			{
				Log.d("BroadCastReceiver", "mBroadcastIntent----------INTENT_ACTION_1"+"\n"
											+ intent.getStringExtra("person_info"));
				if (mIsOrderBroadcast) {

					Bundle bundle = new Bundle();
					bundle.putString("mBroadcastIntent", "mBroadcastIntent data to second broadcastReceiver");
					setResultExtras(bundle);
					mIsOrderBroadcast = false;
				}
			}

		}
	};

	private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {				// 注6

		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			// 如果捕捉到的action是ACTION_BATTERY_CHANGED
			if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
				// 当未知Intent包含的内容,则需要通过以下方法来列举
				StringBuffer strTemp = new StringBuffer();
				Bundle b = intent.getExtras();
				Object[] lstName = b.keySet().toArray();

				for (int i = 0; i < lstName.length; i++) {
					String keyName = lstName[i].toString();
					strTemp.append(keyName + String.valueOf(b.get(keyName))
							+ "\n");
				}
				Log.d("BroadCastReceiver", "mBatInfoReceiver----------ACTION_BATTERY_CHANGED"+"\n"
						+ strTemp);
			}
			// 如果捕捉到的action是INTENAL_ACTION_3
			if (INTENAL_ACTION_3.equals(action)) {
				Log.d("BroadCastReceiver", "mBatInfoReceiver----------INTENAL_ACTION_3"+"\n"
						+ intent.getStringExtra("name"));
			}
		}
	};
}

 

注1:

 静态注册,就是在androidMainfest.xml中注册

<receiver android:name=".Test1BroadCastReceiver"> 
            <intent-filter> 
                <action android:name="com.potato.INTENT_ACTION_1" /> 
            </intent-filter>
</receiver> 


注2:

sendBroadcast(intent);

触发Test1BroadCastReceiver,Test1BroadCastReceiver和动态注册的INTENAL_ACTION_1

注3:

sendBroadcast(intent, BLUETOOTH_PERMISSION);

这里加了权限,BLUETOOTH_PERMISSION是蓝牙的权限,如果没有在androidMainifest.xml中加了权限,则会收不到;

 

注4:

动态注册BroadcastReceiver

通过registerReceiver(mBroadcastIntent, intentFilter);注册mBroadcastIntent

IntentFilter intentFilter = new IntentFilter(INTENAL_ACTION_2);				// 注4
		intentFilter.addAction(INTENAL_ACTION_1);

增加action;

	@Override
	protected void onStart() {
		super.onStart();
		// 动态注册
		IntentFilter intentFilter = new IntentFilter(INTENAL_ACTION_2);				// 注4
		intentFilter.addAction(INTENAL_ACTION_1);
		// 也可以用这种方法动态注册多个,说明我可以”接收“这么多的动态广播。
		/*
		 * IntentFilter intentFilter= new IntentFilter();
		 * intentFilter.addAction("action1"); intentFilter.addAction("action2");
		 */
		registerReceiver(mBroadcastIntent, intentFilter);
	}

在unregisterReceiver(mBroadcastIntent);中注销;

@Override
	protected void onStop() {
		super.onStop();																// 注4
		unregisterReceiver(mBroadcastIntent);
		unregisterReceiver(mBatInfoReceiver);
	}

在中接收BroadcastReceiver mBroadcastIntent中处理;

// 接收动态注册广播的BroadcastReceiver
	private BroadcastReceiver mBroadcastIntent = new BroadcastReceiver() {				// 注4
		@Override
		public void onReceive(Context context, Intent intent) {
			// 多个广播
			if (intent.getAction().equals("com.potato.INTENT_ACTION_2")) {
				Log.d("BroadCastReceiver", "mBroadcastIntent----------INTENT_ACTION_2");
			}

			if (intent.getAction().equals("com.potato.INTENT_ACTION_1"))
			{
				Log.d("BroadCastReceiver", "mBroadcastIntent----------INTENT_ACTION_1"+"\n"
											+ intent.getStringExtra("person_info"));
			}

		}
	};

 

注5:

 注册多个广播

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);// 系统电量检测信息
filter.addAction(INTENAL_ACTION_3);// 第三组自定义消息
registerReceiver(mBatInfoReceiver, filter);

注册多个action,Intent.ACTION_BATTERY_CHANGED(系统的,测试电池变化),INTENAL_ACTION_3

 

注6:

接收Intent.ACTION_BATTERY_CHANGED.equals(action),INTENAL_ACTION_3.equals(action);

通过action判断是哪个广播发送的;

注7:

sendOrderedBroadcast(intent, BLUETOOTH_PERMISSION);

发送有序的broadcast;

intentFilter.setPriority(700); 

增加了权限,权限值越大,优先级越高;

如果把权限值都去掉,则结果无法预料:

TestBroadCastReceiver.java

BroadcastReceiver实现接收者;

package com.potato;

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

public class TestBroadCastReceiver extends BroadcastReceiver
{
	@Override
	public void onReceive(Context context, Intent intent)
	{
		// TODO Auto-generated method stub
		Bundle bundle = getResultExtras(true);

		String receiverMsg = bundle.getString("mBroadcastIntent");

		if (null != receiverMsg) {

			Log.d("BroadCastReceiver", receiverMsg);
		}
		
		// 对比Action决定输出什么信息

		if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
		{
			Toast.makeText(context, "成功接收广播", 10000).show();
		}

		if (intent.getAction().equals("com.potato.INTENT_ACTION_2")) {
			Log.d("BroadCastReceiver", "TestBroadCastReceiver----------INTENT_ACTION_2");
		}
		
		if (intent.getAction().equals("com.potato.INTENT_ACTION_1"))
		{
			Log.d("BroadCastReceiver", "TestBroadCastReceiver----------INTENT_ACTION_1"+"\n"
					+ intent.getStringExtra("person_info"));
		}

	}
}

bundle,是接受广播的信息;

Test1BroadCastReceiver.java

package com.potato;

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

public class Test1BroadCastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent)
	{
		// TODO Auto-generated method stub
		Bundle bundle = getResultExtras(true);

		String receiverMsg = bundle.getString("mBroadcastIntent");

		if (null != receiverMsg) {

			Log.d("BroadCastReceiver", receiverMsg);
		}

		// 对比Action决定输出什么信息

		if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
		{
			Toast.makeText(context, "成功接收广播", 10000).show();
		}

		if (intent.getAction().equals("com.potato.INTENT_ACTION_2")) {
			Log.d("BroadCastReceiver", "Test1BroadCastReceiver----------INTENT_ACTION_2");
		}
		
		if (intent.getAction().equals("com.potato.INTENT_ACTION_1"))
		{
			Log.d("BroadCastReceiver", "Test1BroadCastReceiver----------INTENT_ACTION_1"+"\n"
										+ intent.getStringExtra("person_info"));
		}

	}

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button  
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    android:text="Implict  Intent(String action)"
	    android:id="@+id/btn_implict_intent_broadcast"/>
    
    <Button  
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    android:text="Auto(String action)"
	    android:id="@+id/btn_auto_broadcast"/>
    
    <Button  
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    android:text="MutilAuto(String action)"
	    android:id="@+id/btn_mutil_auto_broadcast"/>
    
    <Button  
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    android:text="orderBroadcast(String action)"
	    android:id="@+id/btn_order_broadcast"/>
</LinearLayout>

AndroidMainifest.xml

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

    <uses-sdk android:minSdkVersion="8" />  <uses-permission android:name="android.permission.BLUETOOTH"/>         <application         android:icon="@drawable/ic_launcher"         android:label="@string/app_name" >         <activity             android:label="@string/app_name"             android:name=".BroadcastDemoActivity" >             <intent-filter >                 <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>                 <receiver android:name=".Test1BroadCastReceiver">             <intent-filter android:priority="600">                 <action android:name="com.potato.INTENT_ACTION_1"/>             </intent-filter>

            <intent-filter>                 <action android:name="android.intent.action.BOOT_COMPLETED" />             </intent-filter>         </receiver>                 <receiver android:name=".TestBroadCastReceiver">             <intent-filter  android:priority="500">                 <action android:name="com.potato.INTENT_ACTION_1"/>             </intent-filter>

            <intent-filter>                 <action android:name="android.intent.action.BOOT_COMPLETED" />             </intent-filter>         </receiver>     </application>

</manifest>

增加蓝牙权限

    <uses-sdk android:minSdkVersion="8" />
	<uses-permission android:name="android.permission.BLUETOOTH"/>

静态注册了TestBroadCastReceiver,Test1BroadCastReceiver;

  


开发BroadcastReceiver的一些注意事项:

BroadcastReceiver的生命周期比较短,一些比较费时的操作不应该放在onReceiver里完成。如果在onReceiver()的方法不能在10秒内执行完成,将会产生程序无响应也就是我们熟悉的ANR(Application not Response)。但是如果非得要在这里面执行一些费时的操作我们可以在这个onReceiver去启动一个Service来完成这样的一个费时操作

附加功能,开机通过broadcast启动service

在androidMainfest.xml中增加权限

首先开机启动后系统会发出一个Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED,这个Action只会发出一次

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

在receiver中增加

<receiver android:name=".TestBroadCastReceiver"> 
	<intent-filter> 
		<action android:name="android.intent.action.BOOT_COMPLETED" /> 
		<category android:name="android.intent.category.LAUNCHER" /> 
	</intent-filter> 
</receiver> 

只要在接受者启动service就可以了。。。。。。。。。。

public class TestBroadCastReceiver extends BroadcastReceiver
{
	@Override
	public void onReceive(Context context, Intent intent)
	{
		if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
               {
                  Toast.makeText(context, "Test1BroadCastReceiver+成功接收广播", 10000).show();
               }
	}
}

 

 

有问题请留言或者发邮箱:ligexiao@gmial.com


源代码下载源代码下载


 

抱歉!评论已关闭.