android启动广播
‘壹’ Android启动广播时怎样往广播中传递参数
在android中使用广播来让其他监听广播的地方能够对相应的事情做处理,但有的时候需要传递一些其他的附带值,而这个时候是可以直接用播放广播的intent来传递的。x0dx0a例:x0dx0aIntent intent = new Intent();x0dx0aintent.putExtra("msgPersons", msgPersons);x0dx0aintent.setAction(Constant.hasMsgUpdatedAction);x0dx0aintent.putExtra("userId", userId);x0dx0aintent.putExtra("msgCount", messages.size());x0dx0asendBroadcast(intent);
‘贰’ Android本地广播的使用
为了解决广播的安全性问题,Android引入了本地广播机制,使用该机制发出的广播只能在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。
本地广播是无法通过静态注册的方式来接收的。我们知道静态注册主要是为了在程序未启动的情况下能接收广播,而当我们发送本地广播的时候,程序肯定是已经启动的了,所以我们需要动态注册方式创建接收器。
在这里我们创建一个继承于BroadcastReceiver的类LocalReceiver。onReceive()处理你接收到的广播内容,在这里我用Toast来创建一个提示接收到消息的弹窗
在activity_main.xml文件创建一个用于发送广播的按钮
首先通过本地广播管理器LocalBroadcastManager的getInstance()方法获取一个实例,并分别创建过滤器IntentFilter和自定义接收器LocalReceiver的实例。给IntentFilter的实例添加一个action:localbroadcast(接收的广播的名称),然后调用LocalBroadcastManager的registerReceiver()方法进行注册,并将LocalReceiver的实例和IntentFilter的实例都传进去。这样本地监听器就创建完成了。
调用LocalBroadcastManager的sendBroadcast()发送本地广播。运行程序,点击Send Button按钮,我们可以看到弹窗显示“This is in LocalReceiver”,说明本地广播发送和接收成功了。
当然,我们最后一定不要忘了取消注册。我们可以通过调用unregisterReceiver()方法来实现。至此,Android的标准广播发送就完成了。
1.发送的广播只能在本程序内传递,不必担心数据泄露
2.其它程序广播无法发送到本程序的内部,不必担心安全漏洞隐患
3.本地广播比系统全局广播更加高效
‘叁’ 安卓开机广播是什么意思
就是android 系统开机的时候会发送一个广播,应用程序注册的这个广播的话就可以收到,通常很多应用就会启动后台服务
‘肆’ 说说Android的广播(1)
对于Activity的启动流程,我们已经有了几个版本的分析了。这里我们分析一个更容易一些的,四大组件中最简单的Broadcast Receiver。
关于Broadcast,有几点需要了解。首先是广播的类型,然后是广播的发送方法,最后是广播是如何被接收的。这三者相辅相承的,比如普通广播和有序广播只有在详细了解了广播的接收过程了之后,才能真正明白它的含义。
普通的广播是不在意顺序的,最简单的理解是同时可以收到这个广播。如果应用是动态注册这个广播的,且广播发送时这个进程还活着,那么当然可以并发的把广播尽快地传送出去是最好的。
但是,如果是通过AndroidManifest.xml静态注册的情况,也就是说这个广播首先要把一个进程启动起来,这时并发启动很多进程就是个问题了。Android目前的做法是,对这种静态的广播接收者,自动按有序广播的方式来串行处理。但是这对应用是透明的,应用不能假设系统已经把静态的无序广播当成有序广播来处理。
这个时候讲粘性广播有福了,因为从Android 5.0(API 21)开始,因为安全性的问题,官方已经正式废弃了粘性广播。
Context类提供两个方法可以用于发送普通广播:
差别是第二个设置权限。
发给特定的用户:
有序广播因为要处理消息的处理结果,所以要复杂一些。
如果只是想让广播可以按优先级来收取,并不在意处理的结果,可以用下面的版本:
同样,在多用户环境下,也可以选择给哪个用户发广播:
不管是普通的还是有序的广播都对应有粘性的版本:
以上的API都是定义于Context类中: https://developer.android.com/reference/android/content/Context.html
首先我们先看看发送端是如何发送的。
我们首先先放一个大图,让大家先有一个直观的印象,不管普通广播、有序广播、粘性广播如何组合,最终都汇集到一个大方法中。
我们先看应用发送普通广播的一个简单的例子:
非常简单,调用ContentWrapper的sendBroadcast方法就可以了。
然后我们顺藤摸瓜就好了。
Activity中的sendBroadcast,实际上调用的是:
我们来看frameworks/base/core/java/android/content/ContextWrapper.java中对sendBroadcast的定义:
ContextWrapper只是一个包装,真正的实现在ContextImpl中
我们来看/frameworks/base/core/java/android/app/ContextImpl.java中真正实现sendBroadcast的功能:
它会通过IPC去调用AMS的broadcastIntent。由于我们这个普通的广播的方法参数最少,所以好多都是传null。
加锁,定参数,然后调用真正的逻辑的实现。
我们先把broadcastIntentLocked的真正逻辑放一下,先看看有序广播是如何发送的。
ContextWrapper.sendOrderedBroadcast
Context是abstract方法,调用的是ContextWrapper的实现:
跟普通广播一样,还是会调用到ContextImpl.sendOrderedBroadcast
有序广播调用broadcastIntent的区别在于serialized参数,普通广播为false,有序广播为true.
原型为:
前面讲过带有回调的版本,我们看看它是如何实现的:
当然还是调用ContextImpl.sendOrderedBroadcast
这次变成只是一个封装了,它会调用一个更多参数的版本:
这次是一个全参数调用broadcastIntent的版本了,除了sticky就齐了
我们也不绕圈子了,直接看ContextImpl.sendStickyBroadcast.
‘伍’ Android 使用广播系统解决app开机自启动问题
关注 【网罗开发】微信公众号,回复【160】便可领取。
网罗天下方法,方便你我开发 ,更多Android技术干货等待领取,所有文档会持续更新,欢迎关注一起成长!
总结一下使用ACTION_BOOT_COMPLETED的广播,解决app开机自启动的问题
1.首先在你的工程上建一个广播接受的类,继承BroadcastReceiver:
2.然后要在AndroidManifest.xml中加入权限和配置相关信息:
3.在application标签中,配置以下相关信息:
补充说明:
1.查看系统中是否安装了类似360管家的软件,为了加快开机速度,默认是关闭掉开机广播的,只需要在设置中打开即可。
2.如果监听不到广播,可以尝试同时监听广播和sd卡。
3.同时监听广播和sd卡,在application标签中,配置以下相关信息:
‘陆’ android 之广播机制
Android 中的广播主要可以分为两种类型:标准广播和有序广播
一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎会在同一时刻收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断
标准广播工作示意图:
一种同步执行的广播,在广播发出之后,同一时刻只会有一个BroadcastReceiver能够收到这条广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才会继续传递。所以此时的BroadcastReceiver是有先后顺序的,优先级高的BroadcastReceiver就可以先收到广播消息,并且前面的BroadcastReceiver还可以截断正在传递的广播,这样后面的BroadcastReceiver就无法收到广播消息了
有序广播工作示意图:
可以让程序在未启动的情况下接收广播
在Android 8.0系统之后,所有隐式广播都不允许使用静态注册的方式来接收了。隐式广播指的是那些没有具体指定发送给哪个应用程序的广播,大多数系统广播属于隐式广播,但是少数特殊的系统广播目前仍然允许使用静态注册的方式来接收,详见网址: https://developer.android.google.cn/guide/components/broadcast-exceptions.html
在 AndroidManifest.xml 文件中注册
在 AndroidManifest.xml 文件中进行权限声明
不要在 onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为BroadcastReceiver中是不允许开启线程的,当 onReceive() 方法运行了较长时间而没有结束时,程序就会出现错误
先定义一个BroadcastReceiver来准备接收此广播
在 AndroidManifest.xml 文件中注册
有序广播是一种同步执行的广播,并且是可以被截断的。为了验证这一点,我们需要再创建一个新的BroadcastReceiver。新建AnotherBroadcastReceiver
同样,在 AndroidManifest.xml 文件中注册,同时,使用 intent-filter 标签的 android:priority 属性设置优先级
前面的 AnotherBroadcastReceiver 的优先级比较高,因此 AnotherBroadcastReceiver 一定比 MyBroadcastReceiver 先收到广播,因此,可以在 AnotherBroadcastReceiver 的 onReceive 方法中使用 abortBroadcast() 方法截断广播,这样 MyBroadcastReceiver 就收不到该广播了
在界面上弹出一个对话框,让用户无法进行任何其他操作,必须点击对话框中的“确定”按钮,关闭所有的Activity,然后回到登录界面即可
ActivityCollector 类用于管理所有的Activity,具有关闭所有Activity的功能
创建 BaseActivity 类作为所有 Activity 的父类,并在里面实现强制下线功能,在这里实现此功能,有以下几点原因
创建一个LoginActivity来作为登录界面
activity_login.xml
LoginActivity 如果输入 123 就到 MainActivity界面
MainActivity 中点击强制下线按钮,就发送强制下线的广播
MainActivity 布局