一,BroadcastReceiver是什么?
- BroadcastReceiver用于接收程序(包括用户开发的程序和系统内建的程序)所发出的Broadcast Intent
- 与activity、service相同的是,程序启动broadcastreceiver也只需要两步
- 1,创建需要启动的BroadcastReceiver的Intent
- 2,调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver。
- 与activity、service具有完整的声明周期不同,BroadcastReceiver本质上只是一个系统级的监听器–它只负责监听各个程序所发出的Broadcast(与之不同的,比如activity中的onXxxListener只是程序级别的监听器,当程序退出时,该监听器就随之关闭了)
二、BroadcastReceiver的实现
- 实现起来很简单,只需要重写BroadcastReceiver中的onReceiver(Context context,Intent intent)方法即可。
- 一旦实现了BroadcastReceiver,接下来就应该指定该BroadcastReceiver能匹配的Intent,此时有两种方式。
1,使用代码进行指定,调用BroadcastReceiver的Context的RegisterReceiver(BroadcastReceiver receiver,IntentFilter filter)方法指定,例如如下代码:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomingSMSReceiver();
registerReceiver(receiver,filter);
2,在AndroidManifest.xml文件中进行配置,例如如下代码:
<receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<intent_filter>
</reveiver>
每次系统Broadcast事件发生后,系统就会创建对应的BroadcastReceiver实例,并自动触发它的onReceiver()方法,onReceiver()方法执行完成后,BroadcastReceiver实例就会被销毁。
注:
1,与activity组件不同的是,当系统通过Intent启动制定了activity组件时,如果系统没有找到合适的activity组件,则会导致程序异常终止,但是系统通过intent激发BroadcastReceiver时,如果找不到合适的BroadcastReceiver组件,应用不会有任何问题。
2,如果BroadcastReceiver的onReceive()方法不能在10s内执行完成,Android会认为该程序无响应,所以在BroadcastReceiver的onReceive()方法里不要执行一些耗时的操作
三、发送广播
在程序中发送广播十分简单,只需要调用Context的sendBroadcast(Intent intent)方法即可,这条广播将会启动intent参数所对应的BroadcastReceiver。
下面示范一下如何发送Broadcast、使用BroadcastReceiver来接收广播。该程序的Activity界面中包含一个按钮,当用户点击该按钮时程序会向外发送一条广播。
MainActivity.java
package com.zt.broadcasereceivetest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
String BroadcastAction = "android.provider.Broadcast1";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button sendBroadcast;
sendBroadcast = (Button)findViewById(R.id.sendBroadcast);
sendBroadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建Intent对象,并用该Intent对象对外发送一条广播
//设置Intent对象
Intent intent = new Intent();
//设置Intent的Action属性
intent.setAction(BroadcastAction);
intent.putExtra("msg","简单的消息1");
sendBroadcast(intent);
}
});
}
}
MyReceiver.java
package com.zt.broadcasereceivetest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
/**
* Created by 邹涛 on 2017/4/10.
*/
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"接收到的Intent的Action为: " + intent.getAction(),Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml 中对于MyReceiver所能接收的广播的Action的配置
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.provider.Broadcast1" />
</intent-filter>
</receiver>
运行结果:
正如上面程序中看到的,当符合该MyReceiver的广播出现时,该MyReceiver的onReceive()方法将会被触发,从而在该方法中显示广播所携带的消息。
注意:上面广播程序中指定发送广播时所用的Intent的Action为 android:provider:Broadcast1,这是在AndroidManifest.xml中配置的MyReceiver所应该监听的Action。
四、有序广播
Broadcast分为两种:
Normal Broadcast(普通广播):完全异步,可以在同一时刻被所有接收者收到,消息传递效率高,前面代码示例则为普通广播,缺点是接收者不能将处理结果传递给下一个接收者,并且无法终止Broadcast Intent的传播。使用Context提供的sendBroadcast()方法来发送广播。
Ordered Broadcast(有序广播):有序广播接收者将按照预先声明的优先级一次接受Broadcast。比如:A级别高于B,B级别高于C,那么广播先传给A,再传给B,最后传给C。有序广播接收者可以终止Broadcast Intent的传播,传播一旦终止,后面的接收者就无法接收到广播了。另外,有序广播的接收者可以将数据传递给下一个接收者。使用Context提供的sendOrderedBroadcast()方法来发送有序广播。
注意:对于有序广播而言,优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast,然后传给下一个接收者,下一个接收者通过代码:
Bundle bundle = getResultExtras(true);
来获取上一个接收者存入的数据。
下面给一段发送有序广播的示例,Activity界面中只有一个普通按钮,用于发送一条有序广播。代码如下:
MainActivity.java
package com.zt.broadcasereceivetest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
String BroadcastAction = "android.provider.Broadcast2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button sendBroadcast;
sendBroadcast = (Button)findViewById(R.id.sendBroadcast);
sendBroadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(BroadcastAction);
intent.putExtra("msg","简单的消息1");
//发送有序广播
sendOrderedBroadcast(intent, null);
}
});
}
}
MyReceiver1.java
package com.zt.broadcasereceivetest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
/**
* Created by 邹涛 on 2017/4/10.
*/
public class MyReceiver1 extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = new Bundle();
bundle.putString("first","第一个BroadcastReceiver存入的消息");
setResultExtras(bundle);
//也可以取消广播的继续传播
//abortBroadcast();
}
}
MyReceiver2.java
package com.zt.broadcasereceivetest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
/**
* Created by 邹涛 on 2017/4/10.
*/
public class MyReceiver2 extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
//解析前一个BroadcastReceiver所存入的key为first的消息
String first = bundle.getString("first");
Toast.makeText(context,"第一个BroadcastReceiver存入的消息为: "+first,Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml中的对于MyReceiver1、MyReceiver2所能接收到的广播的Action的配置:
<receiver android:name=".MyReceiver1" >
<intent-filter android:priority="20">
<action android:name="android.provider.Broadcast2"/>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver2">
<intent-filter android:priority="10">
<action android:name="android.provider.Broadcast2"/>
</intent-filter>
</receiver>
值得注意的一点是每一个BroadcastReceiver的优先级priority取值范围为-1000~1000。
根据上面配置可以看出,该程序中包含两个BroadcastReceiver,其中MyReceiver1的优先级比MyReceiver2的优先级更高,如果将MyReceiver1中的取消广播的代码注释取消,那么MyReceiver2将不会再接收到广播了。
运行结果:
五、接收系统广播消息
除了接收用户发送的广播之外,BroadcastReceiver还有一个重要用途:接收系统广播,如果应用需要在系统特定时刻执行某些操作,就可以通过监听系统广播来实现,Android常见广播的Action常量如下:
- ACTION_TIME_CHANGED: 系统时间被改变。
- ACTION_DATE_CHANGED: 系统日期被改变。
- ACTION_TIMEZONE_CHANGED: 系统时区被改变。
- ACTION_BOOT_COMPLETED: 系统启动完成
- ACTION_PACKAGE_CHANGED: 系统的包改变。
- ACTION_PACKAGE_ADDED:系统添加包。
- ACTION_PACKAGE_REMOVED:系统的包被移除。
- ACTION_PACKAGE_RESTARTED:系统的包被重启。
- ACTION_PACKAGE_DATA_CLEARED: 系统的包数据被清空。
- ACTION_BATTERY_CHANGED:电池电量改变。
- ACTION_BATTERY_LOW:电池电量低。
- ACTION_POWER_CONNECTED:系统连接电源。
- ACTION_POWER_DISCONNECTED:系统与电源断开。
- ACTION_SHUTDOWN: 系统被关闭。
通过使用BroadcastReceiver来监听特殊的广播,即可让应用随系统执行特定的操作。
比如:开机自动运行的Service
在AndroidManifest.xml中配置LauchReceiver.java中Activity所能监听的广播的Action为 监听系统启动。
<receiver android:name=".LauchReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
在加上访问系统开机事件的权限。
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
而在LauchReceiver.java中,可以自己定义应用在Android系统开机之后所要做的动作。
六、学习总结
BroadcastReceiver使用起来较为简单,也比较容易理解,功能很强大,也很实用,可以适合于Android开发中的很多功能场景。
写博客真的是个好习惯,建议大家在学习或者了解一些新的知识点之后再博客中记录,不仅仅可以方便日后的查阅,也可以让自己对知识更加的熟悉了解。
–致我的第一篇学习记录
–邹啊涛