android广播机制
来源:互联网 发布:易到打车软件 编辑:程序博客网 时间:2024/06/05 23:57
一:广播机制简介
BroadCastReciver:广播接收者,它的作用是用来接受系统和应用发送过来的广播的。
我们先来了解什么是广播:android系统是离不开广播的,比如手机电量改变时系统就会发送一条广播提示用户;当手机开机时系统会发送一条广播,接受到广播就能实现开机启动服务的功能;当没有网络时也会发送一条广播,提示作相应的操作。
接下来我们来了解一下广播的类型, android中的广播可以分为两种类型:标准广播和有序广播
标准广播:
是一种异步执行的广播,广播发出后,所有的广播接收器几乎会在同一时刻接收到这条广播消息,因此它们没有先后顺序可言,效率比较高。但它的缺点是接收者不能将处理结果传递给下一个接受者,并且无法终止BroadCast intent的传播。
标准广播的工作图如下所示:
有序广播:是一种同步执行的广播,这种广播发出后,同一时刻只有一个广播接收器能收到广播消息,当这个广播接收器执行完了之后,广播才会往下传递,因此它是有先后顺序的,那么可以更改它的先后顺序吗?可以 通过以下两种方法更改它的执行顺序:
1:androdManifest<intent-filter.../>元素的android:priority属性中设置它的优先级:取值范围在-1000~1000,数越大优先级越高。
2:也可以调用IntentFilter对象的setPriority()进行设置。
Ordered Broadcast接收者可以终止BroadCast Intent的传播,Broadcastt Intent的传播一旦终止,后面的接收器就无法接收到BroadCast
有序广播的工作图如下所示:
二 接收系统广播
android内置了很多系统级别的广播,我们可以在应用中监听这些广播得到各种系统的状态信息。
如果想要监听广播,就需要使用广播接收器,广播接收器可以自由地对自己感兴趣的广播进行注册。注册广播的方式有两种,
1:在代码中注册
在代码中注册页叫做动态注册
下面我们就通过动态注册来写一个监听网络变化的程序
package broadcastreceiver.csdn.com.aty;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.os.Bundle;import android.os.PersistableBundle;import android.support.annotation.Nullable;import android.widget.Toast;import org.xutils.x;import broadcastreceiver.csdn.com.R;/** * 动态注册广播监听器 * * 监听网络变化 * Created by Administrator on 2017/5/30. */public class DynamicAty extends Activity{ private IntentFilter intentDynamic; private NetworkChangeBR netWorkChangeBR; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.aty_dynnamic); x.view().inject(this); intentBR();//注册广播 } /** * 注册广播 */ private void intentBR() { /** * 创接IntentFilter实例 *IntentFilter对象负责过滤掉组件无法响应和处理的Intent,只将自己关心的Intent接收进来进行处理 */ intentDynamic=new IntentFilter(); /** * 当网络发生改变时系统会发出一条android.net.conn.CONNECTIVITY_CHANGE广播 * * 我们的广播想要监听什么就在这写什么 */ intentDynamic.addAction("android.net.conn.CONNECTIVITY_CHANGE"); /** * 创建NetworkChangeReceiver实例 */ netWorkChangeBR=new NetworkChangeBR(); /** * registerReceiver进行注册 */ registerReceiver(netWorkChangeBR,intentDynamic); } /** * 监听网络变化 * * 建立一个内部类让它继承自BroadcastReceiver */ class NetworkChangeBR extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { /** * 这是一个系统服务类,专门用来管理网络的 */ ConnectivityManager connectivityManager= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); /** * 得到NetworkInfo的实例 */ NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo(); if(networkInfo!=null && networkInfo.isAvailable()){ Toast.makeText(DynamicAty.this,"网络打开了",Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(DynamicAty.this,"网络关闭了",Toast.LENGTH_SHORT).show(); } } } /** * 动态注册的广播接收器一定要取消 * * 取消广播接收器 * */ @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(netWorkChangeBR); }}
这里有非常重要的一点要说明,如果程序涉及一些对用户敏感的操作,就必须在配置文件中声明权限。
android:Manifest中加入以下代码
允许用户访问GSM网络信息
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
2:AndroidManifest.xml中注册
在AndraoidManifest中注册也叫做静态注册
下面我们通过静态注册编写一个能够监听网络变化的应用吧。
右击创建应用的包->New->Other->Broadcast Receiver 会弹出下图所示的窗口
Class Name:输入广播的名字
Exported:是否允许这个广播接收器接收本程序以外的广播
Enabled属性是否启用这个广播接受器
构选这两个属性,点击Finish,广播接收器创建完成了,以下是自动生成的代码
package broadcastreceiver.csdn.com.aty;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;public class QuintReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO: This method is called when the BroadcastReceiver is receiving // an Intent broadcast. throw new UnsupportedOperationException("Not yet implemented"); }}
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="broadcastreceiver.csdn.com"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".aty.MainAty"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".aty.QuintAty" /> <activity android:name=".aty.DynamicAty" /> <receiver android:name=".aty.QuintReceiver" android:enabled="true" android:exported="true"></receiver> </application></manifest>
不过现在还是不能接收广播的,下面我们对代码进行修改
下面是修改后的AndroidMainifest:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="broadcastreceiver.csdn.com"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".aty.MainAty"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".aty.QuintAty" /> <activity android:name=".aty.DynamicAty" /> <receiver android:name=".aty.QuintReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver> </application></manifest>
可以看到我们在两个地方修改了
1、<intent-filter>标签里加了监听系统开机广播action
2、 加了一条开机广播的权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
接下来我们在QuintReceiver加了一条Toast
package broadcastreceiver.csdn.com.aty;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.widget.Toast;/** * 静态注册广播接收器 */public class QuintReceiver 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,"开机了",Toast.LENGTH_SHORT).show(); }}
好了静态注册也完成了
三 发送自定义广播
现在我们已经学会了通过广播接收系统广播,接下来我们来学习如何在应用程序中发送自定义广播。
1:发送标准广播
下面是发送广播的代码
MainAty.class
package broadcastreceiver.csdn.com.aty;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import org.xutils.view.annotation.Event;import org.xutils.view.annotation.ViewInject;import org.xutils.x;import broadcastreceiver.csdn.com.R;public class MainAty extends AppCompatActivity { @Event(value ={R.id.bn_standard,R.id.bn_dynamic}) private void onClick(View v){ switch (v.getId()){ case R.id.bn_dynamic: //动态注册 Intent intentDynamic=new Intent(MainAty.this,DynamicAty.class); startActivity(intentDynamic); break; case R.id.bn_standard: //发送标准广播 Intent intentStandard=new Intent("com.csdn.broadcastreceiver.MY_RECEIVER"); sendBroadcast(intentStandard); break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.aty_main); x.view().inject(this);//xutils3初始化 }}
布局
aty_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteY="81dp"> <Button android:id="@+id/bn_dynamic" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="8dp" android:text="动态注册" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/bn_standard" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="8dp" android:text="发送标准广播" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/bn_dynamic" /></android.support.constraint.ConstraintLayout>
接收广播的代码
package broadcastreceiver.csdn.com.Receiver;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.widget.Toast;/** * 接收自定义广播 */public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"标准广播收到了",Toast.LENGTH_SHORT).show(); }}
AndroidManifest.xml注册
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="broadcastreceiver.csdn.com"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".aty.MainAty"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".aty.QuintAty" /> <activity android:name=".aty.DynamicAty" /> <receiver android:name=".Receiver.QuintReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <receiver android:name=".Receiver.MyReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.csdn.broadcastreceiver.MY_RECEIVER"/> </intent-filter> </receiver> </application></manifest>
思考一个问题,其他程序是否也可以接收该广播呢?我们新建Demo2的项目
Demo2接收广播的代码
package broadcastreceiver.csdn.com.demo2;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.widget.Toast;public class Demo2Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"Demo2也收到了标准广播",Toast.LENGTH_SHORT).show(); }}
AndroidManifest.xml配置代码
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="broadcastreceiver.csdn.com.demo2"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainAty"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".Demo2Receiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.csdn.broadcastreceiver.MY_RECEIVER"/> </intent-filter> </receiver> </application></manifest>
2:发送有序广播
发送有序广播很简单
package broadcastreceiver.csdn.com.aty;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import org.xutils.view.annotation.Event;import org.xutils.view.annotation.ViewInject;import org.xutils.x;import broadcastreceiver.csdn.com.R;public class MainAty extends AppCompatActivity { @Event(value ={R.id.bn_standard,R.id.bn_dynamic}) private void onClick(View v){ switch (v.getId()){ case R.id.bn_dynamic: //动态注册 Intent intentDynamic=new Intent(MainAty.this,DynamicAty.class); startActivity(intentDynamic); break; case R.id.bn_standard: //发送标准广播 Intent intentStandard=new Intent("com.csdn.broadcastreceiver.MY_RECEIVER");// sendBroadcast(intentStandard);//发送标准广播 sendOrderedBroadcast(intentStandard,null);//发送有序广播 break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.aty_main); x.view().inject(this);//xutils3初始化 }}
只要把
sendBroadcast(intentStandard);//发送标准广播换成
sendOrderedBroadcast(intentStandard,null);//发送有序广播
接下来我们来修改它的优先级
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="broadcastreceiver.csdn.com.demo2"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainAty"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".Demo2Receiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="100"> <action android:name="com.csdn.broadcastreceiver.MY_RECEIVER"/> </intent-filter> </receiver> </application></manifest>
我们通过android:priority属性给广播接收器设置了优先级,优先级高的先运行
学习了接收广播的优先级,我们再学一个方法,abortBroadcast(),截断广播,优先级高德广播截断后,优先级低的广播就无法收到了。
package broadcastreceiver.csdn.com.demo2;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.widget.Toast;public class Demo2Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"Demo2也收到了标准广播",Toast.LENGTH_SHORT).show(); abortBroadcast();//将这条广播截断 }}
四 本地广播
有的时候我们发出的广播只要求本地能够接受,这个时候就要用到本地广播,本地广播的特点是发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本地应用程序发出的广播。
下面我们看看代码:
LocalityAty.class
package broadcastreceiver.csdn.com.aty;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.content.LocalBroadcastManager;import android.view.View;import android.widget.Toast;import org.xutils.view.annotation.Event;import org.xutils.x;import broadcastreceiver.csdn.com.R;/** * 本地广播 * Created by Administrator on 2017/5/30. */public class LocalityAty extends Activity{ private String LOCALITY_BROADCAST="com.csdn.broadcastreceiver.LOCALITY_BROADCAST"; private IntentFilter intentFilter; private LocalityReceiver localityReceiver; /** * 本地广播需要使用LocalBroadcastManager对广播进行管理 */ private LocalBroadcastManager localBroadcastManager; @Event(value = {R.id.bn_locality}) private void onClick(View v){ switch (v.getId()){ case R.id.bn_locality: //发送本地广播 Intent intent=new Intent(LOCALITY_BROADCAST); localBroadcastManager.sendBroadcast(intent); break; } } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.aty_locality); x.view().inject(this); localBroadcastManager=LocalBroadcastManager.getInstance(this);//获取实例 intentFilter =new IntentFilter(); intentFilter.addAction(LOCALITY_BROADCAST); localityReceiver=new LocalityReceiver(); localBroadcastManager.registerReceiver(localityReceiver,intentFilter);//注册本地广播监听器 } @Override protected void onDestroy() { super.onDestroy(); localBroadcastManager.unregisterReceiver(localityReceiver); } class LocalityReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Toast.makeText(LocalityAty.this,"收到了本地广播",Toast.LENGTH_SHORT).show(); } }}
aty_locality.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/bn_locality" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="260dp" android:text="本地广播" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.527" /></android.support.constraint.ConstraintLayout>
下面我们来总结一下本地广播的特点吧:
1.本地广播无法通功静态注册
2.本地广播更安全,因为发出的广播不用担心被其他应用监听到,
3.本地广播比全局广播高效
还有一点要说明的是广播接收器里不能进行耗时操作,不能开启多线程
源码下载地址
- [Android]Android广播机制
- android 广播机制
- Android--广播机制
- Android 广播机制
- android 广播机制
- Android 广播机制 详解
- Android广播机制
- android 广播机制
- android 广播机制
- android广播机制
- Android 中的广播机制
- Android广播机制
- android 广播机制
- Android 广播事件机制
- Android学习--广播机制
- Android的广播机制
- 图解 Android 广播机制
- Android 广播机制
- 字符串类型的转换之toString()示例
- PHP中刷新输出缓冲详解
- poj 2752 找到所有的公共前后缀
- SpringBoot-整合MyBatis
- Java关键字transient和volatile
- android广播机制
- java使用ResourceBundle访问资源文件(.properties文件)
- POJ1703 并查集
- HTTP状态码详解
- 消息中间件-activemq安全机制
- 【剑指offer-解题系列(36)】 数组中的逆序对
- 远程桌面控制软件
- Java日期格式化-线程安全
- HDU2454 判定简单图