您的位置:首页 > 移动开发

AndroidWiki - APP作恶之开机广播监听

2018-03-05 17:59 295 查看
1 开机广播事件和静态广播机制

1.1 开机广播事件
通过BroadcastReceiver获取SDcard,Usb连接和开机事件 
链接:http://blog.chinaunix.net/uid-20771867-id-300200.html

usb和电量
链接:http://blog.csdn.net/wds1181977/article/details/50381509

1.2 静态广播与同步反馈以及ANR机制

对无序以及有序广播的静态广播接收者的调用过程需要先判断其所附属的进程是否存在,
如果不存在需要先启动其所附属的进程,然后进程启动之后就将广播发送给其所在的应用进程,
其所在的进程接收到广播之后则继续分发给具体的接收者,当广播接收者执行完毕之后需要将结果反馈给ActivityManagerService,
以便让ActivityManagerService继续将广播分发下一个接收者,
如果在分发一个广播给接收者的过程中超时了则会产生ANR。

2 系统启动的监听
Intent.BOOT_COMPLETED 
权限:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
链接:http://blog.csdn.net/mmmccc000/article/details/53335552

1.在使用 BOOT_COMPLETED 广播时,必须要 RECEIVE_BOOT_COMPLETED 权限,这是 4.0 后的修改
  该权限是正常权限,参考官方文档https://developer.android.google.cn/guide/topics/permissions/normal-permissions.html
  如果应用声明其需要正常权限,系统会自动向应用授予该权限。

2.通过指定 priority 属性可以设置 BOOT_COMPLETED 广播的优先级,让该app 早于其他 app 接收到广播
  静态注册的广播接收者总是会按照有序的方式进行处理,导致ActivityManagerService需要串行的响应所有开机监听任务!
3.在 4.4 上 BOOT_COMPLETED 广播是有序广播,但是不可中断(指定了FLAG_RECEIVER_NO_ABORT 字段),而在 4.4 以前,BOOT_COMPLETED 广播
是无序的
  链接:Android4.4KK中BOOT_COMPLETED广播问题的分析http://blog.csdn.net/songjinshi/article/details/46311913
  google为了解决calendar的一个问题将BOOT_COMPLETED的广播发送方式由之前的无序改为了有序,
  同时还进行了延时的发出处理,从而最终影响了整个BOOT_COMPLETED的发送和处理流程,
  导致BOOT_COMPLETED的处理被安排在无序广播之后;
  
  另外由于BOOT_COMPLETED之前还有其他有序广播在待发送队列,
  只有那些有序广播被顺序处理完才会处理BOOT_COMPLETED;
  
  最终在处理有序的BOOT_COMPLETED的时候还会按照优先级进行排序,
  如果此时静态注册的接收者的优先级大于动态注册的优先级则在发送时还会等待静态注册的接收者的进程起来,然后再继续发送,
  所以结果就导致系统动态注册的接收者迟迟接收不到BOOT_COMPLETED,影响系统组件的整体功能体验。

3 对SD卡挂载和卸载的监听

3.1 挂载和卸载
链接:http://blog.csdn.net/guoying_/article/details/6618277
与BOOT_COMPLETED放在同一个intent-filter里,boot complete监听失效,需要分放到两个filter钟。

<receiver android:name=".listener.BootReceiver" >        
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
    <intent-filter >
        <action android:name="android.intent.action.MEDIA_EJECT" />  
        <action android:name="android.intent.action.MEDIA_MOUNTED" />
        <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
        <data android:scheme="file" >
        </data>
    </intent-filter>
</receiver>

3.2 第一次挂载
<intent-filter>  
    <action android:name="android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME" />  
    <data android:scheme="file"/>  
</intent-filter> 

if (action.equals(Intent.ACTION_MEDIA_EJECT)) {  
    //TODO:  

} if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {  
    //TODO:  

} else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {  
    //TODO:  

} else if (action.equals(Intent.MEDIA_MOUNTED_FOR_FIRTIME)) {  
    //TODO:  

}

4 对USB事件的监听

4.1 USB链接
Usb.ACTION_USB_STATE
需要注意的是USB.java类是不包含在android.jar中的,需要为工程引入外部包framework.jar才能正确运行程序。

USBManager.Java发现有一个Aciton:
public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";

IntentFilter filter = new IntentFilter();
filter.addAction(Usb.ACTION_USB_STATE);
registerReceiver(mReceiver, filter);

测试发现这个action生效,但不是即时生效的,
  因为这个action其实是监听USB是否connected,当USB connected时才会生效,有时候你插入了USB,但没connected,这个广播不会发出        
值得注意的是android.hardware.usb.action.USB_STATE是一个粘性的广播,
里面封装USB_CONNECTED(连接状态)、USB_CONFIGURED(配置信息)、USB_FUNCTION_MASS_STORAGE(大存储功能)、USB_FUNCTION_ADB(adb功能) 等状态

从Android 5.0(API 21)开始,因为安全性的问题,官方已经正式deprecated废弃了粘性广播。!!!

4.2 USB3.0之后可以直接调用USBManager的USB各种Aciton
      UsbManager.ACTION_USB_ACCESSORY_ATTACHED
      UsbManager.ACTION_USB_ACCESSORY_DETACHED
      UsbManager.ACTION_USB_DEVICE_ATTACHED
      UsbManager.ACTION_USB_DEVICE_DETACHED

5 其它开机阶段涉及的监听:
5.1 监听电池电量变化Action
Intent.ACTION_BATTERY_CHANGED  

5.2 监听网络变化
android.net.conn.CONNECTIVITY_CHANGE

5.3 屏幕被打开
Intent.ACTION_SCREEN_ON

6 解决方案
6.1 行业实践
华为小米默认关闭了自启动,利用设备管理助手供用户开关;优先级处理;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 开机广播