一、按广播发送的特点:默认情况下,广播接收者的接收顺序就是在功能清单文件中的注册顺序
-
A:正常广播:广播在同一时刻一起发送,接收者会同时收到,其中一个接收者不能终止其它接收者接收广播。
实例化意图对象并指定意图对象的action
Intent intent=new Intent(“android.intent.action.hsj”);
发送正常广播
this.sendBroadcast(intent); -
B:有序广播:根据广播的优先级决定哪个广播接收者先收到广播,并且可以根据需要终止广播,让优先级低的广播永远收不到广播.
如果广播接收方的优先级相同,则接收信号的顺序和注册的顺序一致.
如果广播接收者的优先级不同,则优先级高的接收者优先收到广播,并且高优先级的接收者可以终止广播,让优先级低的广播接收者永远收不到广播
广播接收者的优先级的取值:-1000到1000,数字越大,优先级越高
<receiver android:name=".receivers.BroadcastReceiverOne">
<intent-filter android:priority="100">
<action android:name="hsj"/>
</intent-filter>
</receiver>
<receiver android:name=".receivers.BroadcastReceiverTwo">
<intent-filter android:priority="500">
<action android:name="hsj"/>
<action android:name="wcf"/>
</intent-filter>
</receiver>
<receiver android:name=".receivers.BroadcastReceiverThree">
<intent-filter android:priority="1000">
<action android:name="hsj"/>
<action android:name="wcf"/>
</intent-filter>
</receiver>
发送有序广播:
context.sendOrderedBroadcast(intent,null);
this.sendOrderedBroadcast(intent,null);
发送有序广播并且指定最终广播对象,所谓最终广播对象是:即使前面已经最终了广播,作为最终广播对象一定会收到广播信号的.
this.sendOrderedBroadcast(
intent,//意图对象
null,
new BroadcastReceiverOne(),//指定最终广播对象
null,
100,//初始化码,
null,
null
);
终止广播信号的发送,使其后面的广播接收者收不到广播信号
this.abortBroadcast();
- C:粘滞广播:这种广播会常驻内存,可以先发送广播,之后再注册广播接收者仍然能够收到之前发送的广播.
注册发送粘滞广播需要的权限 发送粘滞广播,必须在功能清单文件中注册发送粘滞广播的权限
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
注册广播
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("hsj");
通过上下文对象动态注册广播接收者
this.registerReceiver(broadCastReceiverTwo, intentFilter);
发送广播
Intent intent=new Intent("hsj");
this.sendStickyBroadcast(intent);
取消注册指定的广播接收者
this.unregisterReceiver(broadCastReceiverTwo);
二、按广播的有效期:
android四大组件中,只有广播接收者可以通过java代码进行注册,其它的都必须在功能清单文件中进行注册;
- A:静态广播:在功能清单文件中注册的广播,即使程序退出,一旦有合适的广播发送仍然能够收到广播的消息
- B:动态广播:在java代码中使用context.registerReceiver(receiver,interfilter);这个方法注册的广播,程序一旦退出,广播接收者就再也收不到广播
消息了。
动态注册广播
IntentFilter intentFilter=new IntentFilter("android.intent.action.hsj");
this.registerReceiver(this.broadcastReceiverTwo, intentFilter);
发送粘滞广播
Intent intent=new Intent("android.intent.action.hsj");
this.sendStickyBroadcast(intent);
取消注册广播
this.unregisterReceiver(this.broadcastReceiverTwo);
自定义广播接收者的步骤:
- 1.编写一个类继承BroadcastReceiver并重写它的声明周期函数:onReceive(Context context, Intent intent)
class BroadcastReceiverOne extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}
- 2.在功能清单文件中注册广播接收者,这种广播成为静态广播;通过Java代码进行注册,这种广播成为动态广播
<receiver android:name=".receiver.BroadcastReceiverOne">
<intent-filter>
<action android:name="android.intent.action.hsj"/>
</intent-filter>
</receiver>
广播接收者的生命周期就是onReceive(Context context, Intent intent)方法的执行期间,这个方法默认运行在主线程中,因此不能做耗时
操作,另外广播接收者的生命周期最长不要超过10秒,因为超过10秒后可能作为被杀死的候选对象,因此不安全.
可以在广播接收者的生命周期函数onReceive(Context context, Intent intent)中启动服务做耗时操作.
三、应用
1、自定义检查手机网络状态是否切换的广播接收者
public class PhoneNetStateCheckBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
//ConnectivityManager.CONNECTIVITY_ACTION即android.net.conn.CONNECTIVITY_CHANGE
if(ConnectivityManager.CONNECTIVITY_ACTION.equals(action)){//说明手机的网络状态发生了化
testConnectionState(context);
}else{
Toast.makeText(context, "当前的广播不是手机网络状态切换的广播!",Toast.LENGTH_LONG).show();
}
}
/**
* 检查手机网络状态的变化
* @param context
*/
private void testConnectionState(Context context) {
ConnectivityManager connectivityManager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo= connectivityManager.getActiveNetworkInfo();
if(networkInfo!=null&&networkInfo.isConnected()){
if(networkInfo.getType()==ConnectivityManager.TYPE_WIFI){
Toast.makeText(context, "当前手机连接了WIFI网络!", Toast.LENGTH_LONG).show();
}else if(networkInfo.getType()==ConnectivityManager.TYPE_MOBILE){
Toast.makeText(context, "当前手机连接了3G网络!", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(context, "当前手机连接了未知网络!", Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(context, "当前无网络!", Toast.LENGTH_LONG).show();
}
}
}
2、短信拦截
- 需要的权限:
<!-- 注册接收短信的权限 -->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<!-- 注册发送短信的权限 -->
<uses-permission android:name="android.permission.SEND_SMS"/>
- 注册广播
<!--注册短信拦截器的广播接收者-->
<receiver android:name=".receivers.SmsInterceptorBroadcastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
- 自定义短信拦截器的广播接收者
public class SmsInterceptorBroadcastReceiver extends BroadcastReceiver {
/**
* 当手机收到短信时系统会发送一个广播,这个广播对应的意图的动作为android.provider.Telephony.SMS_RECEIVED
*/
private String action="android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent) {
String strAction=intent.getAction();
System.out.println("SmsInterceptorBroadcastReceiver.onReceive(Context context, Intent intent).strAction="+strAction);
//说明手机收到短信并且系统发送了广播
if(action.equals(strAction)){
//通过意图得到Bundle对象
Bundle bundle=intent.getExtras();
//通过bundle对象调用get()方法传递的键为pdus则得到一个短信对象数组对应的对象
Object[] objs=(Object[]) bundle.get("pdus");
for(Object obj:objs){
//将短信对象转化成字节数组
byte[] data=(byte[]) obj;
//根据字节数组得到短信消息对象
SmsMessage smsMessage=SmsMessage.createFromPdu(data);
//得到发送短信手机的电话号码
String senderAddress=smsMessage.getOriginatingAddress();
//得到短信内容
String body=smsMessage.getMessageBody();
//得到接收短信的时间
long ldate=smsMessage.getTimestampMillis();
//格式化日期
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=new Date(ldate);
String strDate=simpleDateFormat.format(date);
String receiveSms=senderAddress+"在"+strDate+"时间发送了短信内容为【"+body+"】的短信内容!";
//Toast.makeText(context, receiveSms, Toast.LENGTH_LONG).show();
//终止接收短信的广播
this.abortBroadcast();
//得到短信管理器对象
SmsManager smsManager=SmsManager.getDefault();
String text="zhe niu shi wo de,zai gei lao zi qiang xiao xin lao zi fei le ni!";
//发送短信
smsManager.sendTextMessage(senderAddress, null, text, null, null);
}
}else{
Toast.makeText(context, "并非收到短信的广播!", Toast.LENGTH_LONG).show();
}
}
}
3、电话拦截
- 所需权限
<!-- 注册处理外拨电话的权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
- 功能清单注册广播
<!-- 注册电话拦截器的广播接收者
android.intent.action.NEW_OUTGOING_CALL:当用户外拨电话时anroid系统会发送一个广播,这个广播对应的意图中的action即为:
android.intent.action.NEW_OUTGOING_CALL
-->
<receiver android:name=".receivers.PhoneInterceptorBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
- 自定义电话拦截器的广播接收者
public class PhoneInterceptorBroadcastReceiver extends BroadcastReceiver {
private String action="android.intent.action.NEW_OUTGOING_CALL";
@Override
public void onReceive(Context context, Intent intent) {
String strAction=intent.getAction();
//外拨电话的广播
if(action.equals(strAction)){
//得到外拨电话的电话号码
String phone=this.getResultData();
if(phone.contains("5556")){
//将电话号码置空
this.setResultData(null);
}
}else{
Toast.makeText(context, "并不是外拨电话的广播",Toast.LENGTH_LONG).show();
}
}
}