Android四大组件之BroadcastReceiver
2015-11-09 21:16 叫我小陈 阅读(263) 评论(0) 编辑 收藏 举报广播接收者
现实中:电台要发布消息,通过广播把消息广播出去,使用收音机,就可以收听广播,得知这条消息
Android中:系统在运行过程中,会产生会多事件,那么某些事件产生时,比如:电量改变、收发短信、拨打电话、屏幕解锁、开机,系统会发送广播,只要应用程序接收到这条广播,就知道系统发生了相应的事件,从而执行相应的代码。使用广播接收者,就可以收听广播
创建广播接收者
1. 定义java类继承BroadcastReceiver
2. 在清单文件中定义receiver节点,定义name属性,指定广播接收者java类的全类名
3. 在intent-filter的节点中,指定action子节点,action的值必须跟要接受的广播中的action匹配,比如,如果要接受打电话广播,那么action的值必须指定为
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
* 因为打电话广播中所包含的action,就是"android.intent.action.NEW_OUTGOING_CALL",所以我们定义广播接收者时,
action必须与其匹配,才能收到这条广播
* 即便广播接收者所在进程已经被关闭,当系统发出的广播中的action跟该广播接收者的action匹配时,系统会启动该广播接收者所在的进程,
并把广播发给该广播接收者
简单案例体现广播接受者
ip拨号器
需求:简单判断如果拨打的电话以0开头,视为外地号码,则在原号码前添加17951ip线路,使新号码以17951+原号码的形式拨出去
原理:拨号盘把号码通过广播将数据传递给打电话应用,拨号盘发了一条广播,广播中带着号码数据,拨号盘发的广播在去往打电话的过程中被我们写的项目截下来了,做了修改之后,最后打电话收到的广播中的电话号码是做了修改的号码
输入ip号 点击保存,再下次打电话的时候,就会在有0开头的号码前自动添加上ip号码
//在MainActivity 的click方法中,先拿到ip地址,同sharePreferences方法将输入框中的ip地址拿到并且保存到内存中 public void click(View v) { EditText et = (EditText) findViewById(R.id.et); String ip = et.getText().toString(); SharedPreferences sp = getSharedPreferences("ip", MODE_PRIVATE); sp.edit().putString("ip", ip).commit(); }
public class ipService extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //拿到广播中的数据 String number = getResultData(); if(number.startsWith("0")) { //对数据判断之后,取出内存中的数据 SharedPreferences sp = context.getSharedPreferences("ip", context.MODE_PRIVATE); String ip = sp.getString("ip", ""); number = ip + number; //将修改后的号码重新放到广播中 setResultData(number); } } }
//在写广播接收者方法时要做如下的配置 在清单文件中的注册如下 <receiver android:name="com.example.ip.ipService"> <intent-filter > <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> </intent-filter> </receiver> //同时接收打电话广播需要以下权限 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
案例二 短信防火墙
正常的短信防火墙会从数据库中查询到,要拦截到哪些号码,在下面的案例中我们写死
//接收短信广播的action是android.provider.Telephony.SMS_RECEIVED //如果要拦截断线 还需要设置短信接收者的优先级<intent-filter android:priority="1000" > <receiver android:name="com.example.message.smsMessage"> <intent-filter android:priority="1000" > <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
public class smsMessage extends BroadcastReceiver { //系统创建广播时,把短信存放到一个数组,然后把数据以pdus为key存入bundle,再把bundle存入intent public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object[] objects = (Object[]) bundle.get("pdus"); for (Object ob : objects) { SmsMessage sms = SmsMessage.createFromPdu((byte[]) ob); if((sms.getOriginatingAddress()).equals("123")){; abortBroadcast(); } } } }
System.out.println(sms.getMessageBody());//可以得到短信的内容
* 4.0以后广播接收者安装以后必须手动启动一次,否则不生效
* 4.0以后广播接收者如果被手动关闭,就不会再启动了
我可以通过广播来监听sd卡的状态
//清单文件中定义广播接收者接收的类型,监听SD卡常见的三种状态,所以广播接收者需要接收三种广播 <receiver android:name="com.itheima.sdcradlistener.SDCardReceiver"> <intent-filter > <action android:name="android.intent.action.MEDIA_MOUNTED"/> <action android:name="android.intent.action.MEDIA_UNMOUNTED"/> <action android:name="android.intent.action.MEDIA_REMOVED"/> <data android:scheme="file"/> </intent-filter> </receiver>
public class SDStatusReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //判断收到的到底是什么广播 String action = intent.getAction(); if("android.intent.action.MEDIA_MOUNTED".equals(action)){ Toast.makeText(context, "SD卡可用", 0).show(); } else if("android.intent.action.MEDIA_REMOVED".equals(action)){ Toast.makeText(context, "SD卡拔出", 0).show(); } else if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){ Toast.makeText(context, "SD卡不可用", 0).show(); } } }
通过广播接受者 ,实现开机自动启动
<receiver android:name="com.example.shoujileisuo.service"> <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> //权限 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
public class service extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //设置意图对象,开机重启界面 Intent it = new Intent(context, MainActivity.class); //广播接收者的启动并不会创建任务栈,没有任务栈就无法启动activity,手动创建设置新任务栈 it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(it); } }
监听应用的安装、卸载、更新
原理:应用在安装卸载更新时,系统会发送广播,广播里会携带应用的包名
<receiver android:name="com.example.jianting.receive"> <intent-filter > <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.PACKAGE_REPLACED"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <data android:scheme="package"/> </intent-filter> </receiver>
public class receive extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Uri uri = intent.getData(); if("android.intent.action.PACKAGE_ADDED".equals(action)) { Toast.makeText(context, uri.toString() + "被安装了", 0).show(); } if("android.intent.action.PACKAGE_REMOVED".equals(action)) { Toast.makeText(context, uri.toString() + "被卸载了", 0).show(); } if("android.intent.action.PACKAGE_REPLACED".equals(action)){ Toast.makeText(context, uri.toString() + "被升级了", 0).show(); } } }
发送自定义广播
//发送广播端
public void click(View v) { Intent intent = new Intent(); intent.setAction("com.example.zdy"); sendBroadcast(intent); }
//接收广播端
//做清单文件注册
<receiver android:name="com.example.receive.receive">
<intent-filter >
<action android:name="com.example.zdy"/>
</intent-filter>
</receiver>
发送有序广播
广播的两种类型
无序广播:所有跟广播的intent匹配的广播接收者都可以收到该广播,并且是没有先后顺序(同时收到)
有序广播:所有跟广播的intent匹配的广播接收者都可以收到该广播,但是会按照广播接收者的优先级来决定接收的先后顺序
优先级的定义:-1000~1000
最终接收者:所有广播接收者都接收到广播之后,它才接收,并且一定会接收
abortBroadCast:阻止其他接收者接收这条广播,类似拦截,只有有序广播可以被拦截
public void click(View v) { Intent intent = new Intent(); intent.setAction("com.example.fdm"); sendOrderedBroadcast(intent, null, new resultReceiver(),null , 0, "发1000", null); } class resultReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String rice = getResultData(); Toast.makeText(context, rice, 0).show(); } }
<receiver android:name="com.itheima.local.ShengZF"> <intent-filter android:priority="1000"> <action android:name="com.itheima.fdm"/> </intent-filter> </receiver> <receiver android:name="com.itheima.local.ShiZF"> <intent-filter android:priority="800"> <action android:name="com.itheima.fdm"/> </intent-filter> </receiver> <receiver android:name="com.itheima.local.XianZF"> <intent-filter android:priority="600"> <action android:name="com.itheima.fdm"/> </intent-filter> </receiver>
public class ShengZF extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String text = getResultData(); System.out.println("省政府收到文件:" + text); setResultData("每人发80斤大米"); } }
public class ShiZF extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String text = getResultData(); System.out.println("市政府收到文件:" + text); abortBroadcast(); } }
public class XianZF extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String text = getResultData(); System.out.println("县政府收到文件:" + text); } }