首页 文章 精选 留言 我的

精选列表

搜索[组件化],共10000篇文章
优秀的个人博客,低调大师

Android Day07四大组件之广播接收者BroadcastReceiver

1.广播和广播接收者 Android中的广播和广播接收者相当于现实生活中的电台和听收音机的人, Android系统内部相当于已经定义好了电台, 就是内部定义好了一些事件(外拨电话,短信到来 电池电量低 sd卡状态 卸载安装 开机启动等等),我们开发者只需要注册这个事件就ok了(注册事 件就是创建广播接收者之后在清单里配置意图过滤器的action属性,相当于听收音机的人调频一样) 更确切的说,广播接收者就是Android系统的全局监听者,可以监听系统的很多事件,只要广播 接收者注册了这些事件,就会被这些事件触发。 广播接收者被触发,底层原理应该是广播事件会利用隐式意图启动符合条件的广播接收者. 2.注册广播接收者 注册广播接收者有2种方式,而且一个广播接收者配置多个过滤动作Action。 第1种:在清单里注册 在配置文件中注册的接收者的特点是即使应用程序已被关闭,该接收者依然可接受它感兴趣的广播。 上面红色特性,已经验证过,确实如此! 一般大多数的广播接收者都是在清单文件中注册,只有少量的广播接收者是在代码里注册 当然可以在清单里注册的广播接收者,也一定能够在代码里注册。 第2种:在Activity里注册 在Activity中绑定接收者必须依附该应用程序存在,或者一个BroadcastReceiver用于更新UI,就没有必要在 程序关闭时接收者还运行,故无需在AndroidManifest.xml中注册而可以放在Activity中注册。 操作特别频繁的广播事件 比如 锁屏和解锁这种广播接收者在清单文件里面注册是无效的 必需在代码里注册,否则会报下面这个异常。 MainActivity has leaked IntentReceiver ScreenReceiver@b65bb500 that was originally registered here. Are you missing a call to unregisterReceiver()? 代码里注册广播接收者 首先,定义一个类继承BroadcastReceiver: public class ScreenReceiver extends BroadcastReceiver 下一步,在一个Activity中注册上面定义的广播接收者 1 2 3 4 5 6 7 ScreenReceiverscreenReceiver= new ScreenReceiver(); //创建意图对象过滤器 IntentFilterintentFilter= new IntentFilter(); intentFilter.addAction( "android.intent.action.SCREEN_OFF" ); intentFilter.addAction( "android.intent.action.SCREEN_ON" ); //注册锁屏和解锁广播 registerReceiver(screenReceiver,intentFilter); 3.广播接收者开发步骤 第1步:定义一个类继承广播接收者,并在清单或代码里注册,包括receiver的name属性、 过滤器的Action属性。 第2步:复写定义的广播接收者类的onReceive方法,定义广播接收者被触发后想实现的逻辑。 一般如果广播接收者注册了多个事件,还得先判断一下事件的类型。 1 2 3 4 public void onReceive(Contextcontext,Intentintent){ //得到事件的类型 Stringaction=intent.getAction(); } 案例:注意不同的案例获取数据的方式 4.案例1_IP拨号器(外拨电话) ■清单配置 1 2 3 4 5 6 < receiver android:name = "com.itheima.ipdialerListener.OutGoingReceiver" > < intent-filter > <!--配置actionnewoutgoingcall--> < action android:name = "android.intent.action.NEW_OUTGOING_CALL" /> </ intent-filter > </ receiver > ■权限 1 < uses-permission android:name = "android.permission.PROCESS_OUTGOING_CALLS" /> ■广播接收者的接收后的逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class OutGoingReceiver extends BroadcastReceiver{ @Override public void onReceive(Contextcontext,Intentintent){ //获取广播事件的数据-电话号码 StringphoneNumber=getResultData(); //直接调用BroadcastReceiver的方法 System.out.println( "phoneNumber:" +phoneNumber); //假如电话号码开头是0,就是长途。 if (phoneNumber.startsWith( "0" )) { phoneNumber= "95128" +phoneNumber; } //改变广播当前的数据-用修改过后电话号码替换。 setResultData(phoneNumber); //注意这个方法只能与有序广播联用 } } 将应用程序安装好,拨打一个手机号以0开始的电话号码0123,点击拨打按钮,效果如下所示: 5.案例2_sd卡状态监听 ■清单配置 注意过滤器里多了一个<data android:scheme="file"/> 1 2 3 4 5 6 7 < receiver android:name = "com.itheima.sdcard.SDCardReceiver" > < intent-filter > < action android:name = "android.intent.action.MEDIA_MOUNTED" /> < action android:name = "android.intent.action.MEDIA_UNMOUNTED" /> < data android:scheme = "file" /> </ intent-filter > </ receiver > ■权限 1 无 ■广播接收者的接收后的逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class SDCardReceiver extends BroadcastReceiver{ @Override public void onReceive(Contextcontext,Intentintent){ //因为清单里有2个action,所以要获取action的类型。 Stringaction=intent.getAction(); if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) { System.out.println( "sd卡挂载了" ); } else if (Intent.ACTION_MEDIA_UNMOUNTED.equals(action)){ System.out.println( "sd卡卸载了" ); } else { System.out.println( "sd监听出错了" ); } } } 进入2.3这些低版本的模拟器,settings-storage里面可以模拟sd的挂载与卸载。 6.案例3_短信监听器 短信监听的底层原理,应该是短信数据库内容提供者者安插了内容观察者,一旦手机接收到短 信,势必短信数据库会发生变化,内容观察者分析到了就会发送一条短信接收的广播,并且把短 信相关的信息封装在了意图对象里。 ■清单配置 高版本的ADT提示里没有action对应的选项,应从低版本ADT拷贝action值到清单中。 1 2 3 4 5 < receiver android:name = "com.itheima.msglistener.MsgListener" > < intent-filter > < action android:name = "android.provider.Telephony.SMS_RECEIVED" /> </ intent-filter > </ receiver > ■权限 1 < uses-permission android:name = "android.permission.RECEIVE_SMS" /> ■广播接收者的接收后的逻辑 注意SmsMessage对象所在的包 1 2 3 4 5 6 7 8 9 10 11 12 13 //获取短信数据,可能有多条短信数据吧。 //由此可见,短信的数据在intent里的封装的格式是Bundle,也就是map集合。 Object[]object=(Object[])intent.getExtras().get( "pdus" ); //创建SmsMessage对象来分离短信的各项内容,注意SmsMessage所在的包。 for (Objectobj:object){ //创建SmsMessage实例,解析短信信息:发送者、短信内容 SmsMessagesmsMessage=SmsMessage.createFromPdu(( byte [])obj); StringmessageBody=smsMessage.getMessageBody(); StringoriginatingAddress=smsMessage.getOriginatingAddress(); System.out.println( "短信发送者:" +originatingAddress); System.out.println( "短信内容:" +messageBody); } 关于短信监听,android2.3版本时没有考虑到安全问题,4.0之后,考虑到安全问题,广播接 收者需要有一个启动界面才能生效(但不一定要求界面就要启动,也就是说只要有个activity就行了 )。 对于用户来说,在2.3这些低版本设备上,对于没有界面的短信监听应用,如果一旦有短信发送过 来,应用就会被激活,在setting中的forcestop按钮也才会变得可选,可以在setting中点击这个按 钮就能关闭应用 对于流氓程序员来说,不但可以做个没有启动界面和图标的应用,更可以结合卸载监听事件,不让 安装的流氓应用卸载,还可以加个密码确认之后才能输入,要多流氓就有多流氓。 7.案例4_应用安装与卸载的监听 ■清单配置 注意过滤器多了一个<data android:scheme="package" /> 1 2 3 4 5 6 7 < receiver android:name = "com.itheima.packageaddandremove.PackageReceiver" > < intent-filter > < action android:name = "android.intent.action.PACKAGE_ADDED" /> < action android:name = "android.intent.action.PACKAGE_REMOVED" /> < data android:scheme = "package" /> </ intent-filter > </ receiver > ■权限 1 无 ■广播接收者的接收后的逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 //得到包名 UripackageName=intent.getData(); //获取事件类型 Stringaction=intent.getAction(); if ( "android.intent.action.PACKAGE_ADDED" .equals(action)) { System.out.println(packageName+ "安装了。。。。。" ); } else if ( "android.intent.action.PACKAGE_REMOVED" .equals(action)) { System.out.println(packageName+ "卸载了。。。。。" ); } 8.案例5_开机启动监听 如果想在广播接收者里启动activity,必须要为意图指定一个任务栈标记。 ■清单配置 ■权限 ■广播接收者的接收后的逻辑 开机启动广播监听,可以与很多地方相结合。如启动activity或service,可以在service里又与 其它的监听事件如短信、电话监听相结合,做出电话窃听器这样子之类的应用。 另外,开机启动监听比较的费时,有时候其实是实现了,但是 Log就是不出信息,可以采用开 启Activity的方式(记得intent要setFlags),这样效果就明显了。 #################################################################################### 上面讲到几个案例,都有一个共同的特点:广播都是由系统发送的。那么可以自己定义并发送广播吗? 查看API会发现Context类有发送广播的方法,Activity和Service都继承了Context,所以这两个对象 都可以发送广播,或者只要有Context对象的对象都可以发送广播。广播就是在发送Intent,Intent用 来封装数据并且过滤广播接收者,发送广播有2种方式:(系统发送广播也是用的这2个方法) 1.发送无序广播 ■发送广播代码:sendBroadcast 1 2 3 4 5 6 7 8 9 10 public void sendUnOrder(Stringcontent) { Intentintent= new Intent(); //注意设置意图对象的action,以便过滤发送给哪个广播接收者。 intent.setAction( "com.itheima.UNORDER_SEND" ); intent.putExtra( "content" ,content); //无序广播的发送方法 sendBroadcast(intent); } ■广播接收者清单配置: 只要定义一个广播接收者,在清单里配置它的action属性和发送代码里的action参数一样,发送广 播的方法就会将意图Intent发送给符合条件的广播接收者的onReceive参数里,这也印证了为什么广播 接收者的接收方法里会有一个Intent参数的原因:onReceive参数里的Intent就是发送这个广播的对象 传递的Intent。 2.发送有序广播 ■发送广播代码:sendOrderedBroadcast 1 2 3 4 5 6 7 public void sendOrder(Stringcontent) { Intentintent= new Intent(); intent.setAction( "com.itheima.ORDER_SEND" ); //注意有序广播的发送方法 sendOrderedBroadcast(intent, null , new FinalReceiver(), null , 1 ,content, null ); } ■广播接收者清单配置: 和接收无序广播的广播接收者不同,接收有序广播的广播接收者的过滤器除了要配置action 标签之外,过滤器本身还要设置priority属性,表示过滤器的优先级,优先级高的过滤器的广播 接收者会优先接收到广播。 终极接收者无须在清单配置任何信息,连receiver也不用配置。 ■广播接收者接收广播代码: 3.有序广播与无序广播的区别(**********重点***********) ■有序广播 广播的数据可以被修改,广播可以被拦截,但是终极接收者仍然可以接受到。 ■无序广播 广播的数据不可以被修改,广播不可以被拦截。 --------------------------------广播的一些异常------------------------------------ 1)IllegalStateException: Can not perform this action after onSaveInstanceState http://www.tuicool.com/articles/yU3Yji http://stackoverflow.com/questions/7575921/illegalstateexception-can-not-perform-this-action-after-onsaveinstancestate-wit 一是要解注册广播,二是在fragmentManager提交的时候采用 transaction.commitAllowingStateLoss(); 本文转自屠夫章哥 51CTO博客,原文链接:http://blog.51cto.com/4259297/1679400,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册