Android零基础入门 | 广播机制 Broadcast Android应用可以通过广播从系统或其他App接收或发送消息。类似于订阅-发布设计模式。当某些事件发生时可以发出广播。 系统在某些状态改变时会发出广播例如开机、充电。App也可发送自定义广播。广播可用于应用间的通讯是IPC的一种方式。广播的种类广播的种类也可以看成是广播的属性。标准广播Normal Broadcasts完全异步的广播。广播发出后所有的广播接收器几乎同时接收到这条广播。 不同的App可以注册并接到标准广播。例如系统广播。有序广播Ordered Broadcasts同步广播。同一时刻只有一个广播接收器能接收到这条广播。这个接收器处理完后广播才会继续传递。 有序广播是全局的广播。本地广播Local Broaddcasts只在本App发送和接收的广播。注册为本地广播的接收器无法收到标准广播。带权限的广播发送广播时可以带上相关权限申请了权限的 App 或广播接收器才能收到相应的带权限的广播。 如果在 manifest 中申请了相应权限接收器可以不用再申请一次权限即可接到相应广播。接收广播创建广播接收器调用onReceive()方法需要一个继承 BroadcastReceiver 的类。注册广播代码中注册称为动态注册。在AndroidManifest.xml中注册称为静态注册。动态注册的刚波接收器一定要取消注册。在onDestroy()方法中调用unregisterReceiver()方法来取消注册。不要在onReceive()方法中添加过多的逻辑操作或耗时的操作。因为在广播接收器中不允许开启线程当onReceive()方法运行较长时间而没结束时程序会报错。因此广播接收器一般用来打开其他组件比如创建一条状态栏通知或启动一个服务。新建一个MyExampleReceiver继承自BroadcastReceiver。publicclassMyExampleReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Context context,Intent intent){Toast.makeText(context,Got it,Toast.LENGTH_SHORT).show();//abortBroadcast();}}abortBroadcast()可以截断有序广播在AndroidManifest.xml中注册广播接收器android:name里填接收器的名字。 可以设置广播接收器优先级intent-filter android:priority100receiver android:name.MyExampleReceiverintent-filteraction android:namecom.rust.broadcasttest.MY_BROADCAST//intent-filter/receiver让接收器接收到一条com.rust.broadcasttest.MY_BROADCAST广播。 发送自定义广播标准广播时要传送这个值。例如Intent intentnewIntent(com.rust.broadcasttest.MY_BROADCAST);sendBroadcast(intent);发送有序广播应当调用sendOrderedBroadcast()Intent intentnewIntent(com.rust.broadcasttest.MY_BROADCAST);sendOrderedBroadcast(intentnull);发送广播App有3种发送广播的方式。发送广播需要使用Intent类。sendOrderedBroadcast(Intent, String)发送有序广播。每次只有1个广播接收器能接到广播。 接收器接到有序广播后可以完全地截断广播或者传递一些信息给下一个接收器。 有序广播的顺序可受android:priority标签影响。同等级的接收器收到广播的顺序是随机的。sendBroadcast(Intent)以一个未定义的顺序向所有接收器发送广播。也称作普通广播。 这种方式更高效但是接收器不能给下一个接收器传递消息。这类广播也无法截断。**LocalBroadcastManager.sendBroadcast 广播只能在应用程序内部进行传递并且广播接收器也只能接收到来自本应用程序发出的广播。 这个方法比全局广播更高效不需要Interprocess communicationIPC而且不需要担心其它App会收到你的广播以及其他安全问题。广播与权限发送带着权限的广播当你调用sendBroadcast(Intent, String)或sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)时你可以指定一个权限。 接收器在manifest中申请了相应权限时才能收到这个广播。例如发送一个带着权限的广播sendBroadcast(newIntent(com.example.NOTIFY),Manifest.permission.SEND_SMS);接收广播的app必须注册相应的权限uses-permission android:nameandroid.permission.SEND_SMS/当然也可以使用自定义。在 manifest 中使用 permission 标签permission android:namecustom_permission/添加后编译一下。即可调用Manifest.permission.custom_permission接收带权限的广播若注册广播接收器时申明了权限那么只会接收到带着相应权限的广播。在配置文件中声明权限程序才能访问一些关键信息。 例如允许查询系统网络状态。uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE/!--机器开机广播--uses-permission android:nameandroid.permission.BOOT_COMPLETED如果没有申请权限程序可能会意外关闭。使用示例发送和接收广播。分为发送和接收方2个App。使用带权限的广播。系统权限与自定义权限。 使用权限需要在AndroidManifest.xml中声明。如果是自定义权限需要先添加自定义权限。!--自定义的权限 给广播用--permission android:namecom.rust.permission_rust_1/uses-permission android:namecom.rust.permission_rust_1/发送广播时带上权限声明。接收方不论是否己方App需要在AndroidManifest.xml中申请权限。 注册接收器时也需要声明权限。发送不带权限的有序广播Intent intentnewIntent(MSG_PHONE);sendOrderedBroadcast(intent,null);Log.d(TAG,[RustFisher-App1] 发送不带权限的有序广播, intent.getAction());发送方App1代码privatestaticfinal StringTAGrustApp;publicstaticfinal StringMSG_PHONEmsg_phone;publicstaticfinal StringPERMISSION_RUST_1com.rust.permission_rust_1;// onCreate注册广播接收器registerReceiver(mStandardReceiver1,makeIF());registerReceiver(mStandardReceiver2,makeIF());registerReceiver(mStandardReceiver3,makeIF());registerReceiver(mStandardReceiverWithPermission,makeIF(),Manifest.permission.permission_rust_1,null);// 带上权限LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalReceiver1,makeIF());LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalReceiver2,makeIF());LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalReceiver3,makeIF());// 解除接收器unregisterReceiver(mStandardReceiver1);unregisterReceiver(mStandardReceiver2);unregisterReceiver(mStandardReceiver3);unregisterReceiver(mStandardReceiverWithPermission);LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalReceiver1);LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalReceiver2);LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalReceiver3);// 发送标准广播privatevoidsendStandardBroadcast(){Intent intentnewIntent(MSG_PHONE);sendBroadcast(intent);Log.d(TAG,[RustFisher-App1] Dispatcher 发送标准广播);}// 发送带权限的标准广播privatevoidsendStandardBroadcastWithPermission(){Intent intentnewIntent(MSG_PHONE);sendBroadcast(intent,PERMISSION_RUST_1);Log.d(TAG,[RustFisher-App1] Dispatcher 发送带权限的标准广播);}// 发送本地广播privatevoidsendAppLocalBroadcast(){Intent intentnewIntent(MSG_PHONE);LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);Log.d(TAG,[RustFisher-App1] Dispatcher 发送本地广播);}privateIntentFiltermakeIF(){IntentFilter intentFilternewIntentFilter(MSG_PHONE);intentFilter.addAction(Intent.ACTION_TIME_TICK);intentFilter.addAction(Intent.ACTION_TIME_CHANGED);returnintentFilter;}// 标准接收器 用context来注册privateBroadcastReceiver mStandardReceiver1newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 标准接收器1 收到: intent.getAction());}};// 标准接收器 用context来注册privateBroadcastReceiver mStandardReceiver2newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 标准接收器2 收到: intent.getAction());if(intent.getAction().endsWith(MSG_PHONE)){abortBroadcast();// 截断有序广播Log.d(TAG,[RustFisher-App1] 标准接收器2截断有序广播 intent.getAction());}}};// 标准接收器 用context来注册privateBroadcastReceiver mStandardReceiver3newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 标准接收器3 收到: intent.getAction());}};// 注册的时候给它带权限 标准接收器privateBroadcastReceiver mStandardReceiverWithPermissionnewBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 带权限的标准接收器收到: intent.getAction());}};/** * 用LocalBroadcastManager来注册成为本地接收器 * 收不到标准广播 - 不论是本app发出的还是别的地方发出来的 */privateBroadcastReceiver mLocalReceiver1newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 本地接收器1 收到: intent.getAction());}};privateBroadcastReceiver mLocalReceiver2newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 本地接收器2 收到: intent.getAction());}};privateBroadcastReceiver mLocalReceiver3newBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[RustFisher-App1] 本地接收器3 收到: intent.getAction());}};接收方App2代码!--自定义的权限 给广播用--permission android:namecom.rust.permission_rust_1/uses-permission android:namecom.rust.permission_rust_1/publicstaticfinal StringMSG_PHONEmsg_phone;// onCreate里注册接收器registerReceiver(mDefaultReceiver,makeIF());LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalReceiver,makeIF());unregisterReceiver(mDefaultReceiver);LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalReceiver);privateBroadcastReceiver mDefaultReceivernewBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[App2] standard receive: intent.getAction());}};privateBroadcastReceiver mLocalReceivernewBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){Log.d(TAG,[App2] local receive: intent.getAction());}};privateIntentFiltermakeIF(){IntentFilter intentFilternewIntentFilter(MSG_PHONE);intentFilter.addAction(Intent.ACTION_TIME_TICK);intentFilter.addAction(Intent.ACTION_TIME_CHANGED);returnintentFilter;}使用LocalBroadcastManager发出的本地广播另一个App是接收不到的。 要收到本地广播同样需要LocalBroadcastManager来注册接收器。可以把本地广播看成是一个局部的App内的广播体系。实验中我们注意到Intent.ACTION_TIME_TICK广播是可以截断的。监听屏幕亮灭使用广播监听设备屏幕亮灭状态。这个是系统发出来的广播。使用的action是Intent.ACTION_SCREEN_ON 亮屏Intent.ACTION_SCREEN_OFF 灭屏privatevoidregisterScreenListener(){IntentFilter filternewIntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(mScreenReceiver,filter);}privateBroadcastReceiver mScreenReceivernewBroadcastReceiver(){OverridepublicvoidonReceive(Context context,Intent intent){final String actionintent.getAction();if(Intent.ACTION_SCREEN_ON.equals(action)){// 屏幕亮}elseif(Intent.ACTION_SCREEN_OFF.equals(action)){// 屏幕灭}}};Broadcast 相关面试题1. 广播传输的数据是否有限制是多少为什么要限制广播是通过Intent携带需要传递的数据的Intent是通过Binder机制实现的Binder对数据大小有限制不同room不一样一般为1M2. 广播的分类标准广播通过context. sendBroadcast或者context. sendBroadcastAsUser发送给当前系统中所有注册的接受者也就是只要注册了就会接收到。应用在需要通知各个广播接收者的情况下使用如开机启动。有序广播接收者按照优先级处理广播并且前面处理广播的接受者可以中止广播的传递一般通过context. sendOrderedBroadcast或者context.sendOrderedBroadcastAsUser在需要有特定拦截的场景下使用如黑名单短信、电话拦截。粘性广播可以发送给以后注册的接受者意思是系统会将前面的粘性广播保存在AMS中一旦注册了与以保存的粘性广播符合的广播在注册结束后会立即收到广播一般通过context. sendStickyBroadcast或context.sendStickyOrderedBroadcast来发送从字面上看可以看出来粘性广播也分为普通粘性广播和有序粘性广播。本地广播发出的广播只能在应用程序内部进行传递广播接收器也只能接受来自本应用程序的广播。全局广播系统和广播发出的广播可以被其他任何应用程序接收到并且也可以接受到其他任何应用程序的广播。3. 广播的使用场景使用方式广播是一种广泛运用的在应用程序之间传输信息的机制主要用来监听系统或者应用发出的广播信息然后根据广播信息作为相应的逻辑处理也可以用来传输少量、频率低的数据。在实现开机启动服务和网络状态改变、电量变化、短信和来电时通过接收系统的广播让应用程序作出相应的处理。使用//在AndroidManifest中静态注册receiverandroid:name.MyBroadcastReceiverandroid:enabledtrueandroid:exportedtrueintent-filter android:priority100action android:namecom.example.hp.broadcasttest.MY_BROADCAST//intent-filter/receiver//动态注册在代码中注册OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mIntentFilternewIntentFilter();//添加广播想要监听的类型监听网络状态是否发生变化mIntentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);mNetworkChangeReceivernewNetworkChangeReceiver();//注册广播registerReceiver(mNetworkChangeReceiver,mIntentFilter);}OverrideprotectedvoidonDestroy(){super.onDestroy();//取消注册广播接收器unregisterReceiver(mNetworkChangeReceiver);}//发送广播同样通过IntentIntent intentnewIntent(com.example.hp.broadcasttest.MY_BROADCAST);//发送标准广播sendBroadcast(intent);//接收广播publicclassMyBroadcastReceiverextendsBroadcastReceiver{publicMyBroadcastReceiver(){}OverridepublicvoidonReceive(Context context,Intent intent){// TODO: This method is called when the BroadcastReceiver is receiving// an Intent broadcast.Toast.makeText(context,received,Toast.LENGTH_SHORT).show();//将这条广播截断// abortBroadcast();}}4. BroadcastReceiverLocalBroadcastReceiver 区别广播接收者1用于应用间的传递消息 2由于跨应用存在安全问题本地广播接收者1广播数据在本应用范围内传播。 2不用担心别的应用伪造广播。 3比发送全局广播更高效、安全。 4无法使用静态注册5. 在 manifest 和代码中如何注册和使用 BroadcastReceiver1在AndroidManifest中静态注册然后直接使用。 2代码中通过registerReceiver来注册。 3注册发送后在BroadcastReceiver自定义一个接收器继承自BroadcastReceiver的onReceive中接收广播并处理广播。6. 广播引起 anr 的时间限制前台广播BROADCAST_FG_TIMEOUT 10s 后台广播BROADCAST_BG_TIMEOUT 60s最后分享一份【腾讯技术团队出品】Android零基础入门到精通Android Studio安装教程全套安卓基础教程Android编程入门教程Java语言基础从入门到熟悉Kotlin语言基础从入门到熟悉Android 技术栈从入门到熟悉Android Jetpack 全家桶全面学习对于新手来说可能安装Android Studio存在一定困难你可以看着以下视频一步步的跟着学习安装运行Android Studio 安装教程有了Java阶段的学习这一阶段建议以视频学习为主辅以图书查漏补缺。如果以图书为主可以根据图书讲解敲代码辅以教学视频查漏补缺。遇到问题可以去百度入门的问题一般会有很多人遇到并且给出比较好的解答。需要掌握基本知识点比如四大组件如何使用、如何创建Service、如何进行布局、简单的自定义View、动画、网络通信等常见技术。全套零基础教程已经为你们准备好了需要的可以添加下方二维码免费领取全套安卓基础教程