5 四大组件之BroadcastReceiver
5-1 广播与广播接收者
1. 概念:
Android中使用广播这种异步机制来处理组件之间的消息传递
异步广播的好处
可以避免组件之间互相等待而造成的冲突、资源浪费和死锁等
可以大大简化应用层的编程难度 Andorid中的广播采用的是订阅-发布机制
1)Broadcast一种广泛运用的在应用程序之间传输信息的机制
2)BroadcastReceiver,对发送出来的广播进行过滤接收并响应的一类组件,它可以用来接收来自系统和应用中的广播
3)用途
开机完成后系统会产生一条广播
网络状态改变时系统会产生一条广播
电量改变时系统产生一条广播
系统自带的广播:

2. 为什么要设计广播
大大减少开发工作量和周期(程序员不需要关注底层如何实现,只需要掌握BroadcastReceiver就行了)
因为这样的话我们只需要通过广播来进行我们的逻辑代码的时间,这样大大减少开发的工作量和开发周期,作为应用开发者,只需要掌握BroadcastReceiver
3. 使用方法:
a.发送:
ntent intent1 = new Intent(); intent1.setAction("Action1"); intent1.putExtra("Position", "技术员工"); this.sendBroadcast(intent1);
应用层,发送方定义Intent对象,使用所在Context对象的sendBroadcast()方法,将这个Intent发送出去
-把信息装入一个Intent对象(如Action,Category)
-通过调用相应的方法将Intent对象以广播方式发送出去
sendBroadcast()
sendOrderBroadcast()
sendStickyBroadcast()
b.接收:
接收方接收广播时,需要在该广播被发送之前,注册一个BroadcastReceiver其Action属性设置为与要接受广播的Action属性相同的值
registerReceiver()动态注册非常驻型
BroadcastReceiver
IntentFilter inf = new IntentFilter(); inf.addAction("Action1"); inf.addAction("Action2"); this.registerReceiver(receiver, inf);
当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配就会调用BroadcastReceiver的onReceive()方法,所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceive()的方法
注意:
BroadcastReceiver需要注册:
静态注册和代码注册,BroadcastReceiver生命周期只有10秒钟左右
在BroadcastReceiver里不能做一些比较耗时的操作
应该通过发送Intent给Service,由Service来完成
不能使用子线程
广播中的静态注册和动态注册是什么?
静态注册就是实例启动时读取listener.ora文件的配置,将实例和服务注册到监听程序。常驻型,通过AndroidManifest.xml注册,当APP被安装在设备上后,始终处于接收状态,使用<receiver>标签静态注册常驻型BroadcastReceiver
<receiver android:name="Receiver" > <intent-filter> <action android:name="Action" /> </intent-filter> </receiver>
<receiver android:name="Receiver" > <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED" /> </intent-filter> </receiver>
动态注册是在instance启动的时候PMON进程根据init.ora中的instance_name,service_names两个参数将实例和服务动态注册到listener中。通过程序中调用registerReceiver()注册,仅当注册后可以接收广播,且当调用unregisterReceiver()后停止接收广播。
4. 生命周期
生命周期只有5s左右,每次广播来的时候都会创建BroadcastReceiver对象,并调用onReceive()方法。
所以不能在onReceive()做一些耗时操作,可以通过发送Intent给service,由service完成耗时操作。
注意子线程也不行
5. 广播的种类:

注意有序广播是可以终止的,且接收者可以篡改内容。
正常广播
次广播使用Context.sendBroadcast()方法发送,它完全异步。所有的广播接收器是运行在一个无序的状态下
有序广播
次广播调用Context.sendOrderedBroadcast()方法发送,在同一时刻只能传送到一个接收器
粘滞广播
这种广播调用Context.sendStickyBroadcast()方法发送
需要在AndroidManifest.xml中声明android.permission.BROADCAST_STICKY权限
广播接收器的生命周期
一个广播接收器对象只在onReceive(Context, Intent) 方法的执行期间有效
广播接收器的生命周期就是onReceive()方法的执行过程
不要把打开对话框或绑定服务(BindService)等操作放在onReceive()方法中执行

5-2 广播的用法(一)
实现发送广播的步骤:
// 1.将要发送的消息保存在Intent中去
Intent intent = new Intent();
intent.putExtra("msg", "这是一条普通广播");
// 2.设置标识符
intent.setAction("BC_One");
// 3.发送广播
sendBroadcast(intent);
4.重新写好一个类,继承自BroadcastReceiver,其中会实现其中的onReceive的方法,我们可以在其中接收发送出来的广播
5.在主清单文件中去声明一个
<receiver android:name="com.example.android_broadcast.BC1" >
<intent-filter>
<action android:name="BC_One" />
</intent-filter>
</receiver>
这样的标签,其中的action是我们在发送广播的时候设置的action,而receiver中的name就是我们自己写好的继承BroadcastReceiver的那个类的绝对地址
BroadcastReceiver(广播接收者):
广播是一种通信方式,典型的特征有:
1个发送方可以对应若干个接收方,并且具有“频道”的标识需要发送方和接收方共同的遵循。
BroadcastReceiver是Android系统的核心组件。
发送广播与接收广播:
1. 发送方通过调用sendBroadcast(Intent)实现广播的发送,在参数Intent对象中,需要通过Intent的Action属性决定广播的“频道号”。
2. 接收方需要自定义类继承BroadcastReceiver,并在重写的onReceive()方法中处理广播的接收。
3. 注册广播接收者时,需要通过IntentFilter匹配发送方的“频道号”
注册广播接收者:
静态注册:常驻型,通过AndroidManifest.xml注册,当APP被安装在设备上后,始终处于接收状态。
动态注册:通过程序中调用registerReceiver()注册,仅当注册后可以接收广播,且当调用unregisterReceiver()后停止接收广播。
MainActivity.java
package com.example.test; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void doClick(View v){ switch (v.getId()) { case R.id.send1://发送一条普通广播 // 1.将要发送的消息保存在Intent中去 Intent intent=new Intent(); intent.putExtra("msg", "这是一条普通广播"); // 2.设置标识符 intent.setAction("BC_One"); // 3.发送广播 sendBroadcast(intent); break; default: break; } } }
BC1.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class BC1 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String s = intent.getStringExtra("msg"); System.out.println("reveiver1收到消息:"+s); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>


BC2.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class BC2 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String s = intent.getStringExtra("msg"); System.out.println("reveiver2收到消息:"+s); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> <receiver android:name="com.example.test.BC2"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>

---------------------------------------
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter android:priority="100"> <action android:name="BC_One"></action> </intent-filter> </receiver> <receiver android:name="com.example.test.BC2"> <intent-filter android:priority="200"> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>

Ps1:为BroadcastReceiver在主清单文件中设置配置文件的时候,如果在intent-filter中设置了
<intent-filter android:priority="1000">
<action android:name="BC_One" />
</intent-filter>
那么其中的priority就是优先级的设置,取值范围为-10000到10000>(不确定),其中级别低的后收到广播,
----------------------------------------------------------------------------
doClick()方法发送普通广播
新建一个Java类 继承 BroadcastReceiver
创建onReceive方法
AndroidManifest.xml方法中注册一下 receiver
receiver中加intent-filter
intent-filter里加一个priority设置级别
abortbroadcast用于截断广播
静态注册是在AndroidManifest.xml里注册
动态注册是在MainActivity里 new 一个IntentFilter
new BC2
registerReceiver();方法
package com.example.test; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter intentfilter = new IntentFilter("BC_One"); BC2 bc2 = new BC2(); registerReceiver(bc2, intentfilter); } public void doClick(View v){ switch (v.getId()) { case R.id.send1://发送一条普通广播 // 1.将要发送的消息保存在Intent中去 Intent intent=new Intent(); intent.putExtra("msg", "这是一条普通广播"); // 2.设置标识符 intent.setAction("BC_One"); // 3.发送广播 sendBroadcast(intent); break; default: break; } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>

动态注册的接收器优先级比静态注册的接收器高
1.普通广播是不能被截断的,在androidmanifest中可以设置优先级,prioty=200>prioty=100的优先级
2.静态注册就是在AndroidManifest.xml中注册的叫做静态注册
3.动态注册优先级大于静态注册优先级
1)动态注册的BroadcastReceiver优先级要比静态注册的高
2)动态注册有个弊端:如果当前java的程序结束了,动态注册的接收者将不再能收到广播。所以类似于短信拦截的BroadcastReceiver不能用动态注册。
静态注册----在配置文件里注册-----全局有效
动态注册----在代码里注册--------
5-3 广播的用法(二)
普通广播:
MainActivity.java
package com.example.test; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // IntentFilter intentfilter = new IntentFilter("BC_One"); //设置过滤 // BC2 bc2 = new BC2(); // registerReceiver(bc2, intentfilter);//注册接收器 } public void doClick(View v){ switch (v.getId()) { case R.id.send1://发送一条普通广播 // 1.将要发送的消息保存在Intent中去 Intent intent=new Intent(); intent.putExtra("msg", "这是一条普通广播"); // 2.设置标识符 intent.setAction("BC_One"); // 3.发送广播 sendBroadcast(intent); break; default: break; } } }
BC1.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; public class BC1 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String s = intent.getStringExtra("msg"); System.out.println("reveiver1收到消息:"+s); Bundle bundle = new Bundle(); bundle.putString("test", "广播处理的数据"); setResultExtras(bundle); } }
BC2.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; public class BC2 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String s = intent.getStringExtra("msg"); System.out.println("reveiver2收到消息:"+s); //abortBroadcast();//截断广播的方法 Bundle bundle = getResultExtras(true); String s2 = bundle.getString("test"); System.out.println("得到的处理结果是:"+s2); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> <receiver android:name="com.example.test.BC2"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>

接收不到数据;
有序广播:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/send1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="doClick" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:text="发送普通广播" /> <Button android:id="@+id/send2" android:onClick="doClick" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/send1" android:text="发送一条有序广播" /> </RelativeLayout>
MainActivity.java
package com.example.test; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // IntentFilter intentfilter = new IntentFilter("BC_One"); //设置过滤 // BC2 bc2 = new BC2(); // registerReceiver(bc2, intentfilter);//注册接收器 } public void doClick(View v){ switch (v.getId()) { case R.id.send1://发送一条普通广播 // 1.将要发送的消息保存在Intent中去 Intent intent=new Intent(); intent.putExtra("msg", "这是一条普通广播"); // 2.设置标识符 intent.setAction("BC_One"); // 3.发送广播 sendBroadcast(intent); break; case R.id.send2://发送一条普通广播 Intent intent2 = new Intent(); intent2.putExtra("msg", "这是一条有序广播"); intent2.setAction("BC_One"); sendOrderedBroadcast(intent2, null); break; default: break; } } }

BC1.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; public class BC1 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String s = intent.getStringExtra("msg"); System.out.println("reveiver1收到消息:"+s); abortBroadcast(); // Bundle bundle = new Bundle(); // bundle.putString("test", "广播处理的数据"); // setResultExtras(bundle); }


activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/send1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:onClick="doClick" android:text="发送普通广播" /> <Button android:id="@+id/send2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/send1" android:onClick="doClick" android:text="发送一条有序广播" /> <Button android:id="@+id/send3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/send2" android:onClick="doClick" android:text="发送一条异步广播" /> </RelativeLayout>
BC3.java
package com.example.test; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class BC3 extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub System.out.println("收到了异步广播!"); } }
MainActivity .java
package com.example.test; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // IntentFilter intentfilter = new IntentFilter("BC_One"); //设置过滤 // BC2 bc2 = new BC2(); // registerReceiver(bc2, intentfilter);//注册接收器 } public void doClick(View v){ switch (v.getId()) { case R.id.send1://发送一条普通广播 // 1.将要发送的消息保存在Intent中去 Intent intent=new Intent(); intent.putExtra("msg", "这是一条普通广播"); // 2.设置标识符 intent.setAction("BC_One"); // 3.发送广播 sendBroadcast(intent); break; case R.id.send2://发送一条普通广播 Intent intent2 = new Intent(); intent2.putExtra("msg", "这是一条有序广播"); intent2.setAction("BC_One"); sendOrderedBroadcast(intent2, null); break; case R.id.send3://发送一条普通广播 Intent intent3 = new Intent(); intent3.putExtra("msg", "这是一条有序广播"); intent3.setAction("BC_Three"); sendStickyBroadcast(intent3); IntentFilter intentfilter = new IntentFilter("BC_Three"); BC3 bc3 = new BC3(); registerReceiver(bc3, intentfilter); break; } } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.BROADCAST_STICKY"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.example.test.BC1"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> <receiver android:name="com.example.test.BC2"> <intent-filter> <action android:name="BC_One"></action> </intent-filter> </receiver> </application> </manifest>

BC1里
new 一个bundle
bundle.putString
setResultExtras(bundle)
BC2里
getResultExtras
bundle.getString
MainActivity
doClick()的switch语句里添加 case R.id.send2
activity_main
Button中添加onClick
异步广播(这次先发后注册)
MainActivity
doClick()的switch语句里添加 case R.id.send3
改成setAction("BC_Three");
改成sendStickyBroadcast(intent3);
new intentfilter , new BC3, registerReceiver() 三步
Manifest添加BROADCAST_STICKY权限 完成注册
新建一个类 BC3
onReceive方法
动态注册一定要记得用onDestroy()方法里的 unregisterReceiver();卸载掉
异步广播可以先发送后注册接收器
broadcast如果是动态注册一定要在组件结束的时候进行销毁




浙公网安备 33010602011771号