广播BroadcastReceiver

    |     2015年7月21日   |   Receiver广播   |     0 条评论   |    1783

广播是一种广泛应用在应用程序之间传输信息的机制。
在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者可以实现一个广播接收者监听这些广播并做出程序逻辑的处理。

广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此Intent 的多个广播接收者所接收。

BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;

Android广播示意图
QQ截图20150721155254

广播两种实现方式
第一种方式 :静态广播

public class MyBroadcastReceiver extends BroadcastReceiver {
    String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;//接收系统短信广播
 
    public void onReceive(Context context, Intent intent) {
 
       if (intent.getAction().equals( SMS_RECEIVED )) {
           // 相关处理 : 地域变换、电量不足、来电来信;
       }    
   }
}
//系统注册:在 AndroidManifest.xml 中注册
< receiver android:name = ".MyBroadcastReceiver" >
           < intent-filter android:priority = "1000" >
                < action android:name = "android.provider.Telephony.SMS_RECEIVED" />
           </ intent-filter >
</ receiver > 当然了需要权限 :
 
< uses-permission android:name = "android.permission.RECEIVE_SMS" />
< uses-permission android:name = "android.permission.SEND_SMS" />

第二种方式:动态广播

 
// 广播接收者 - 广播的接收
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
 
       @Override
       public void onReceive(Context context, Intent intent) {
           // 相关处理,如收短信,监听电量变化信息
             }
 
    };
 
代码中注册:
IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED " );
registerReceiver( mBatteryInfoReceiver , intentFilter);

广播生命周期

生命周期只有十秒左右,如果在 onReceive() 内做超过十秒内的事情,就会报错 。

每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 所以在BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR(Application NoResponse) 的对话框 . 。

怎么用好 BroadcastReceiver?
如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 . 这里不能使用子线程来解决 , 因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束
BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的
所在进程很容易在系统需要内存时被优先杀死 , 因为它属于空进程 ( 没有任何活动组件的进程 ). 如果它的宿主进程被杀死 , 那么正在工作的子线程也会被杀死 . 所以采用子线程来解决是不可靠的 .

广播类型

普通广播(无序广播) (Normal broadcasts)
发送一个广播,所有监听该广播的广播接收者都可以监听到该广播。

有序广播 (Ordered broadcasts)
按照接收者的优先级顺序接收广播 , 优先级别在 intent-filter 中的 priority 中声明 ,-1000 到1000 之间 , 值越大 , 优先级越高 . 可以终止广播意图的继续传播 . 接收者可以篡改内容 .
abortBroadcast();//中止有序广播向下传播

异步广播(粘性消息)
sendStickyBroadcast(intent);

广播注册与注销

代码中注册广播
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
第一个参数是我们要处理广播的 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。

代码中注销广播:unregisterReceiver(mBatteryInfoReceiver);
在 Activity 中代码注销广播建议在: onPuase() 中注销;

实例代码

/**
 *  BroadcastReceiver作用 :接收过滤响应广播(intent对象)
 * 实现步骤
 * 1.定义BroadcastReceiver
 * 2.注册BroadcastReceiver
 *
 * 
 */
public class SmsBroadCastReceiver extends BroadcastReceiver {
	private static boolean incomingFlag = false;
	private static String incoming_number = null;

	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();

		if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
			Toast.makeText(context, "接收短消息静态广播", Toast.LENGTH_SHORT).show();
			Logs.v("接收短消息静态广播 >>>>>>>>>>>>>>>> ");

		} else if (action.equals(MyReceiverActivity.ACTION_SCXH)) {

			Toast.makeText(context, "自定义静态广播接收到", Toast.LENGTH_SHORT).show();
			Logs.v("自定义静态广播 >>>>>>>>>>>>>>>> ");
			
		} else if (action.equals("android.intent.action.NEW_OUTGOING_CALL")) { 
			//如果是拨打电话
			incomingFlag = false;
			String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
			Logs.i("拨打电话:" + phoneNumber);
			
		} else if (action.equals("android.intent.action.PHONE_STATE")) {
			// 如果是来电
			TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);

			switch (tm.getCallState()) {
			case TelephonyManager.CALL_STATE_RINGING:
				incomingFlag = true;// 标识当前是来电
				incoming_number = intent.getStringExtra("incoming_number");
				Logs.i("来电  :" + incoming_number);
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK:
				if (incomingFlag) {
					Logs.i("摘机(正在通话中) :" + incoming_number);
				}
				break;

			case TelephonyManager.CALL_STATE_IDLE:
				if (incomingFlag) {
					Logs.i("空闲 >>>>>");
				}
				break;
			}

		}

	}

}

系统注册:在 AndroidManifest.xml 中注册

 <receiver android:name="com.warmtel.android.receiver.systemreceiver.SmsBroadCastReceiver" >
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                <action android:name="android.intent.action.PHONE_STATE" />
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
                <action android:name="com.warmtel.android.receiver_ACTION_XH" />
            </intent-filter>
        </receiver>

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

自定义广播发送

Intent intent = new Intent(""com.warmtel.android.receiver_ACTION_XH"");
sendBroadcast(intent);

电话监听

private void receiverPhoneStateListener(){
		// 获取电话通讯服务
		TelephonyManager tpm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
		// 创建一个监听对象,监听电话状态改变事件
		tpm.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);
	}
	class MyPhoneStateListener extends PhoneStateListener {

		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			switch (state) {
			case TelephonyManager.CALL_STATE_IDLE: // 空闲
				Logs.d("空闲 >>>>>  ");
				break;
			case TelephonyManager.CALL_STATE_RINGING: // 来电
				Logs.v("来电 >>>>>  ");
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机(正在通话中)
				Logs.w("摘机(正在通话中) >>>>>  ");
				break;
			}
		}

	}
转载请注明来源:广播BroadcastReceiver
回复 取消