android-BroadcastReceive广播接收器
应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或service来响应它们接收的消息,或者用NotigicationManager来通知用户。通知可以用很多中方式来吸引用户的注意力——闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
广播类型:
普通广播:通过Context.sendBroadcast(Intent myIntent)发生
有序广播:通过Context.sendOrderedBroadcast(intent, reveiverPermission)发送的,该方法第二个参数决定该广播的级别,级别数值是在-1000到1000之间,值越大,发生的优先级越高;广播接受者接收广播时的级别(可通过Intentfilter中的priority进行设置,设为2147483647时优先级最高),同级别接收的先后是随机的,再到级别低的收到广播,高级别或同级别先接收到广播的可以通过abortBroadcast()方法截断广播使其他的接收者无法收到该广播,还有其他构造函数。
异步广播:通过Context.sendStickyBroadcast(Intent myIntent)发送的,还有sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode, initialData, initialExtras)方法,该方法具有有序广播的特性也有异步广播的特性;发送异步广播要:<uses-permission android:name="android.permission.BROADCAST_STICKY"/>权限,接收并处理完Intent后,广播依然存在,直到调用removeStickyBroadcast(intent)主动把它去掉。
注意:发送广播时的intent参数与Context.startActivity()启动起来的Intent不同,前者可以被多个订阅它的广播接收器调用,后者只能被一个Activity或Service调用。
监听广播Intent步骤:
1、写一个继承BroadCastReceiver的类,重写onReceive()方法,广播接收器仅在它执行这个方法时处于活跃状态。当onReceive()返回后,它即为失活状态,注意:为了保证用户交互过程流畅,一些费时的操作要放到线程里。
2、注册该广播接收者,注册有两种方法,动态注册和AndroidManifest中进行静态注册:
静态注册,priority表示接收广播的级别“2147483647”为最高优先级
1 <receiver android:name=".SMSBroadcastReceiver" > 2 <intent-filter android:priority = "2147483647" > 3 <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 4 </intent-filter> 5 </receiver >
动态注册,一般在activity可交互时onResume()内注册BroadcastReceiver
1 IntentFilter intentFilter=new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); 2 registerReceiver(mBatteryInfoReceiver, intentFilter); 3 4 // 反注册 5 unregisterReceiver(receiver);
其中在动态注册中可将BroadcastReceiver的继承类进行封装,添加构造函数和BroadcastReceiver注册。
1 import android.app.Notification; 2 import android.app.NotificationManager; 3 import android.app.PendingIntent; 4 import android.content.BroadcastReceiver; 5 import android.content.Context; 6 import android.content.Intent; 7 import android.content.IntentFilter; 8 9 public class BroadcastReceiverHelper extends BroadcastReceiver { 10 11 NotificationManager mn=null; 12 Notification notification=null; 13 Context ct=null; 14 BroadcastReceiverHelper receiver; 15 16 public BroadcastReceiverHelper(Context c){ 17 ct=c; 18 receiver=this; 19 } 20 21 //注册 22 public void registerAction(String action){ 23 IntentFilter filter=new IntentFilter(); 24 filter.addAction(action); 25 ct.registerReceiver(receiver, filter); 26 } 27 28 @Override 29 public void onReceive(Context context, Intent intent) { 30 // TODO Auto-generated method stub 31 String msg=intent.getStringExtra("msg"); 32 int id=intent.getIntExtra("who", 0); 33 if(intent.getAction().equals("com.cbin.sendMsg")){ 34 mn=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 35 notification=new Notification(R.drawable.icon, id+"发送广播", System.currentTimeMillis()); 36 Intent it = new Intent(context,Main.class); 37 PendingIntent contentIntent=PendingIntent.getActivity(context, 38 0, it, 0); 39 notification.setLatestEventInfo(context, 40 "msg", msg, contentIntent); 41 mn.notify(0, notification); 42 } 43 } 44 }
然后在Activity中声明BroadcastReceiver的扩展对象,在onStart中注册,onStop中卸载。
1 BroadcastReceiverHelper rhelper; 2 @Override 3 public void onStart(){ 4 //注册广播接收器 5 rhelper=new BroadcastReceiverHelper(this); 6 rhelper.registerAction("com.cbin.sendMsg"); 7 super.onStart(); 8 } 9 10 @Override 11 public void onStop(){ 12 //取消广播接收器 13 unregisterReceiver(rhelper); 14 super.onStop(); 15 }
注意:
1、生命周期只有10秒左右,不能多续一秒^-^。如果在onReceive()内做超过十秒内的事情,就好报ANR,如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。这里不能用子线程来解决,因为BroadcastReceiver一旦结束,此时BroadcastReceiver的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程。如果宿主进程被杀死,那么正在工作的子线程也会被杀死。
2、动态注册广播接收器还有一个特点,就是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
系统常见广播Intent如开机启动、电池电量变化、时间改变等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了