Android四大组件之Broadcast Receiver
来源:互联网 发布:javaweb邮件系统源码 编辑:程序博客网 时间:2024/06/05 23:45
Android四大组件之Broadcast Receiver--学习过程中查询资料和书籍自我总结:
基本概念
广播是一个全局监听器,用于接收来自系统和其他APP的广播,每个APP都可以对自己感兴趣的广播进行注册,这样就可以接收到自己关心的广播了并做出对应的响应;
广播分类
- 标准广播:是一种完全异步执行的广播,在发出之后几乎所有程序同时接收到,没有先后顺序;这种广播的效率很高,但同时也是无法被拦截的;通过Context.sendBroadcast(Intent myIntent)发送;
有序广播:是一种同步执行的广播,在发出之后同一时刻只有一个广播接收器能接收到,当这个接收器的逻辑执行完之后,下一个接收器才会接收到,有先后顺序;优先级高的接收器先接收到(同级别接收顺序是随机的),并且前面的接收器还可以拦截广播(使用abortBroadcast()拦截),这样后边的接收器就接收不到这条广播了;通过Context.sendOrderedBroadcast(intent, receiverPermission)发送,第二个参数是广播的级别,级别在-1000-1000之间,值越大优先级越高,可通过intentfilter中的priority进行设置,设为2147483647时优先级最高,也可以通过IntentFilter的setPriority()方法设置;
注册广播
- 动态注册(在代码中注册):新建一个类A继承BroadcastReceiver类,重写onReceiver()方法,当接收到广播时onReceiver就会得到执行,在该方法中编写具体处理逻辑,但要将耗时的操作放到线程中;
//自定义NetWorkChangeReceiver继承BroadcastReceiver class NetWorkChangeReceiver extends BroadcastReceiver { //重写onReceiver方法,进行逻辑处理 public void onReceive(Context context, Intent intent) { //通过getSystemService获取管理网络连接的类ConnectivityManager ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); //获取当前网络状态信息类 NetworkInfo mNetworkInfo = manager.getActiveNetworkInfo(); if (mNetworkInfo != null && mNetworkInfo.isAvailable()) { Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show(); } else Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show(); } }
//在onCreate中注册protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mIntentFilter = new IntentFilter(); mIntentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); mchange = new NetWorkChangeReceiver(); //注册 registerReceiver(mchange, mIntentFilter); }
//最后取消注册protected void onDestroy() { super.onDestroy(); //取消注册 unregisterReceiver(mchange); }
- 静态注册(在AndroidMainfest.xml中注册)
AndroidManifest.xml中注册<receiver android:name=".MyReceivers" android:enabled="true"//是否启用广播 android:exported="true">//是否允许接收本APP外的广播 <intent-filter android:priority="2147483647"> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
public class MyReceivers extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO: This method is called when the BroadcastReceiver is receiving // an Intent broadcast. Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show(); throw new UnsupportedOperationException("Not yet implemented"); }}
动态注册:可以自由的控制注册与注销,使用起来非常灵活,但必须是APP启动之后或者是注册广播的Activity打开后才有效;
静态注册: ,只要设备是开启状态,广播接收器也是打开着的。即使APP未打开接收器也是起作用的;
需要注意的是:广播接收器命周期只有十秒左右,如果在 onReceive() 内做超过十秒内的事情,就会报ANR(Application No Response) 程序无响应的错误信息,如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由Service 来完成 . 这里不能使用子线程来解决 , 因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的所在进程很容易在系统需要内存时被优先杀死 , 因为它属于空进程 ( 没有任何活动组件的进程 ). 如果它的宿主进程被杀死 , 那么正在工作的子线程也会被杀死 . 所以采用子线程来解决是不可靠的;
发送广播
- 发送标准广播:
//DynamicReceiver1,DynamicReceiver2动态注册,DynamicReceiver静态注册public class DynamicReceiver1 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String str = intent.getStringExtra("Dynamic");abortBroadcast();Log.i("DynamicReceiver1", intent.getAction().toString() + " " + str); }}public class DynamicReceiver2 extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String str = intent.getStringExtra("Dynamic");abortBroadcast();Log.i("DynamicReceiver2", intent.getAction().toString() + " " + str); }}public class DynamicReceiver2 extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String str = intent.getStringExtra("Dynamic");abortBroadcast();Log.i("DynamicReceiver2", intent.getAction().toString() + " " + str); }}//button发送Intent mDynamic = new Intent("com.units.jonney.myunits.DYNAMIC_BROADCAST"); mDynamic.putExtra("Dynamic", "send"); sendBroadcast(mDynamic);//注册protected void onResume() { super.onResume(); registerTestReceiver(); }private void registerTestReceiver() { r1 = new DynamicReceiver1(); r2 = new DynamicReceiver2(); r3 = new DynamicReceiver3(); IntentFilter mintent = new IntentFilter(); mintent.addAction("com.units.jonney.myunits.DYNAMIC_BROADCAST"); registerReceiver(r1, mintent); registerReceiver(r2, mintent); registerReceiver(r3, mintent); }<receiver android:name=".DynamicReceiver3" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.units.jonney.myunits.DYNAMIC_BROADCAST"></action> </intent-filter> </receiver>结果:08-26 12:22:29.077 15491-15491/com.units.jonney.myunits I/DynamicReceiver1: com.units.jonney.myunits.DYNAMIC_BROADCAST send08-26 12:22:29.082 15491-15491/com.units.jonney.myunits I/DynamicReceiver2: com.units.jonney.myunits.DYNAMIC_BROADCAST send08-26 12:22:29.082 15491-15491/com.units.jonney.myunits I/DynamicReceiver3: com.units.jonney.myunits.DYNAMIC_BROADCAST send标准广播中动态注册的的接收器会比静态注册的接收器先接收到;
- 发送有序广播:
将上述发送广播的方法由sendBroadcast改为sendOrderBroadcast;
Intent mDynamic1 = new Intent("com.units.jonney.myunits.DYNAMIC_BROADCAST"); mDynamic1.putExtra("Dynamic", "send"); //第二个参数表示如果要接收这个广播要指定权限,处于安全考虑;如果为空则不需要指定权限 sendOrderedBroadcast(mDynamic1, "android.permission.MY_BROADCAST_PERMISSION");
在AndroidManifest.xml中注册和使用权限,并注册另外两个接收器并制定priority属性 <permission android:name="android.permission.MY_BROADCAST_PERMISSION" android:protectionLevel="normal" /><uses-permission android:name="android.permission.MY_BROADCAST_PERMISSION" /><receiver android:name=".DynamicReceiver1" android:enabled="true" android:exported="true"> <intent-filter android:priority="1000"> <action android:name="com.units.jonney.myunits.DYNAMIC_BROADCAST"></action> </intent-filter> </receiver> <receiver android:name=".DynamicReceiver2" android:enabled="true" android:exported="true"> <intent-filter android:priority="900"> <action android:name="com.units.jonney.myunits.DYNAMIC_BROADCAST"></action> </intent-filter> </receiver>在DynamicReceiver1中添加abortBroadcast后:DynamicReceiver1: com.units.jonney.myunits.DYNAMIC_BROADCAST send
在DynamicReceiver1中添加abortBroadcast后:
DynamicReceiver1: com.units.jonney.myunits.DYNAMIC_BROADCAST send
DynamicReceiver2: com.units.jonney.myunits.DYNAMIC_BROADCAST send
- 开机广播:
//接收器public class RootCompleteBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "RootCompleteReceiver"; @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "接收到开机启动广播", Toast.LENGTH_SHORT).show(); Log.i(TAG, "接收到开机启动广播"); }}
<receiver android:name=".RootCompleteBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action><category android:name="android.intent.category.DEFAULT" /></intent-filter> </receiver>不要忘记申请权限 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- 电池状态
public class BatteryStateReceiver extends BroadcastReceiver { private static final String TAG = "BatteryStateReceiver"; public BatteryStateReceiver() { } @Override public void onReceive(Context context, Intent intent) { int current = intent.getExtras().getInt("level"); int total = intent.getExtras().getInt("scale"); float percent = (current / total) * 100; Toast.makeText(context, "当前电量:" + percent + "%", Toast.LENGTH_SHORT).show(); Log.i(TAG, "当前电量:" + percent + "%"); }}
<receiver android:name=".BatteryStateReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
<uses-permission android:name="android.permission.BATTERY_STATS" />一般电池状态监控使用动态注册即可;如果要立即获取当前的电量可以自己手动发送一条电量变化的广播来获取;
- 网络监控
public class NetWorkChangeReceiver extends BroadcastReceiver { private static final String TAG = "NetWorkChangeReceiver"; @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "网络发生改变", Toast.LENGTH_SHORT).show(); Log.i(TAG, "网络发生改变"); ConnectivityManager mconn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mInfo = mconn.getActiveNetworkInfo(); if (mInfo != null && mInfo.isAvailable()) { Toast.makeText(context, "当前网络可用", Toast.LENGTH_SHORT).show(); Log.i(TAG, "当前网络可用"); } else { Toast.makeText(context, "当前网络不可用", Toast.LENGTH_SHORT).show(); Log.i(TAG, "当前网络不可用"); } }
<receiver android:name=".NetWorkChangeReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><category android:name="android.intent.category.DEFAULT" /></intent-filter> </receiver><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- Android四大组件之Broadcast Receiver
- Android的四大组件之Broadcast Receiver
- Android四大组件之Broadcast Receiver
- Android 四大组件 之 Broadcast/Receiver 流程
- Android 四大组件之Broadcast receiver
- Android四大组件之Broadcast Receiver
- Android四大组件之Broadcast Receiver
- android 的四大组件之Broadcast Receiver
- Android四大组件之Broadcast Receiver
- Android四大组件之Broadcast receiver
- Android四大组件之Broadcast Receiver
- 四大组件之Broadcast Receiver
- 四大组件之broadcast receiver
- 四大组件之Broadcast Receiver
- 四大组件之Broadcast Receiver
- Android四大组件--Broadcast Receiver
- android基础知识05:四大组件之Broadcast Receiver
- Android四大组件之广播接收器 Broadcast Receiver
- Java 使用 endorsed 覆盖jdk提供的类
- Kotlin入门
- Android系统内置的各种动画插值器(Intepolator)的效果演示
- LARC DL笔记(四):finetune resnet on food-101
- LINQ基础(一)
- Android四大组件之Broadcast Receiver
- 虚拟筛选涉及的小分子数据库
- jquery里面获取div区块的宽度与高度 和 文本框中只能输入数字
- 通达oa破解补丁/通达oa破解版/通达oa破解补丁下载
- 嵌入式学习28(linux系统函数之文件、文件夹管理相关函数)
- POJ 2774 Long Long Message
- R读取路径下的所有文件和统计
- Android的Gif动画加载
- STL知识(1)--为什么需要有模板?