一.BroadcastReceiver广播接收者简介
BroadcastReceiver广播接收者是Android四大组件之一。一般的都要在AndroidManifest中静态注册,但是只有广播接收者可以使用java代码的方法来动态注册。
BroadcastReceiver是用于接收广播的组件用于组件与组件之间进行通信,可以跨应用程序传递.如操作系统电池电量低会发送一个广播,这样我们的程序里面可以去监听这个广播,可以关 闭程序里面比较耗电的功能,提示用户注意保存进度什么的,还如其它安装新应用等,还有普通应 用程序,例如启动特定线程,文件下载完毕等。
Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。
广播的发送的一般应用场合:发送频率低的情况可以使用,数据量小的情况可以使用。
(一)BroadcastReceiver创建
要创建自己的BroadcastReceiver对象,我们需要继承BroadcastReceiver类,并实现其onReceive 方法。 在onReceive方法内,我们可以获取随广播而来的Intent中的数据,这非常重要,就像无线电一样,包含很多有用的信息。 在创建完我们的BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。所以创建类后就要对BroadcastReceiver进行注册。
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//对接收到的广播进行处理,intent里面包含数据
}
}
(二)BroadcastReceiver注册
1.静态注册
静态注册是在AndroidManifest.xml文件中配置的
<receiver android:name="com.hua.bcreceiver.MyBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
2.动态注册
动态注册需要在代码中动态的指定广播地址并注册
注意,registerReceiver是android.content.ContextWrapper类中的方法,Activity 和Service都继承了ContextWrapper,所以可以直接调用。 在实际应用中,我们在 Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时 如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在 特定的地方执行解除注册操作。
注册代码
MyBroadcastReceiver mbcr = new MyBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(MyBroadcastReceiver.MY_BC_FIRST);
registerReceiver(mbcr, filter);// 注册
(2)解除注册代码,一般在页面销毁时操作
@Override
protected void onDestroy() {
unregisterReceiver(mbcr);
mbcr = null;
super.onDestroy();
}
通过上面两步其实已经完成了一个简单功能的广播接收者,已经可以具有接受广播功能了。在onReceive方法里面就可以做自己想要的处理。
但是上面的BroadcastReceiver注册时的action动作意图值是自己定义的字符串,需要自己发送对应意图的广播才能让上面的广播接收到消息,如果是上面使用系统定义好的动作意图action,那么,就可以接收到系统发过来的广播信息,比如手机接收到短信,手机底层是会发送一条广播,查看手机系统内是否有符合条件的广播接收者,如果有就会向它发送信息。。。
静态注册的广播的程序运行一次后,以后能一直保持广播接收的状态,只要有对应的广播就能接收它的广播信息。而动态注册的广播需要程序在运行中才能接收广播。
关于优先级的说明:
在静态代码块中定义:
<intent-filter android:priority="999">
使用动态java代码设置:
filter.setPriority(999);
优先级的值越大它的优先级就越高。
那么priority的最大值是多少呢?
网上或有些书说的是1000,但是都不正确,正确答案是2147483647这是我通过几个实验得出的数据。优先级的值比它大1都会报错。并且优先级1001确实比优先级1000更快接收到广播。
优先级的范围是:-2147483647到2147483647
刚好它的长度范围是Integer类型数据的最大值4294967296(2的32次方)。
所有我们要知道优先级1000并不是最高的优先级,不信的话你可以试试看效果。
二.发送广播
上面在广播定义好的情况下,我们可以接收系统的广播信息,也可以接收自己发送的广播信息。
问题来了:
如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。
(一)普通广播
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的 接收动作。
主要代码:
Intent intent = new Intent(“myBroadcastReceiver”);
intent.putExtra(“msg”, “这是MainActivity页面发送的广播—-》》”);
sendBroadcast(intent);
(二)有序广播
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。可以在广播注册时使用intent-filter里面的android: priority=”xxx”去解决或在java代码中用setPriority(xxx)来设置。
主要代码:
Intent intent = new Intent(“myBroadcastReceiver”);
intent.putExtra(“msg”, “这是MainActivity页面发送的广播—-》》”);
sendOrderedBroadcast(intent,null);//如果是该自定义的广播接收者发送广播,第二个参数一般为null
对比有序广播和无序广播:
发现他们的使用方式没什么不同,只是有序广播比无序广播要多一个参数;
但是它们的作用是非常不同的,无序广播是不可被截断的,每一个广播接收者都可以收到这个无序广播发送的广播信息;而无序广播时候根据优先级数的大小来判断谁先接收到广播信息,并且可以选择是否截断这个广播信息,如果在某个广播接收者截断信息,在它的优先级之下的广播接收者都接收不到广播信息。
拦截方法: abortBroadcast();
有序广播才能拦截。
三.自定义广播接收者和广播发送的示例
主要展示一下使用步骤和过程的代码!
这里的程序实在两个程序中的,但是也可以写在多个程序中,或单个程序中。程序的效果是一样的。因为BroadcastReceiver任何时候都可以接收广播消息,而发送广播消息,只要有上下文的地方都可以。
(一)程序一的设计
静态广播接收者的接收测试
1.创建第一个广播接收者类
package com.lwz.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* 广播接收者的使用
* 这里使用的是静态注册的方法,等待接收广播
*/
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("Receiver", "这是静态的广播接受者(优先级500)---》" + intent.getStringExtra("msg"));
Toast.makeText(context, "这是使用静态的方法来创建的广播(优先级500)接受者收到消息", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
2.创建第二个广播接收者类
package com.lwz.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* 广播接收者的使用
* 这里使用的是静态注册的方法,等待接收广播
*/
public class MyBroadcastReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("Receiver", "这是静态的广播接受者(优先级999)---》" + intent.getStringExtra("msg"));
Toast.makeText(context, "这是使用静态的方法来创建的广播接受者(优先级999)收到消息", Toast.LENGTH_SHORT).show();
//截断广播
abortBroadcast();
//报错 BroadcastReceiver trying to return result during a non-ordered broadcast
//好像是要有序广播才能截断
}
}
3.在AndroidManifest中注册这两个广播接收者
<receiver android:name=".MyBroadcastReceiver">
<intent-filter android:priority="500">
<action android:name="myBroadcastReceiver" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver2">
<intent-filter android:priority="999">
<action android:name="myBroadcastReceiver" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
注意这里的广播接收者1和2,基本数据是相同的,但是优先级不同。
4.布局文件main_activity.xml的设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="广播的发送" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendToSXL"
android:text="给静态注册的广播发送信息" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendToJava"
android:text="给动态注册的广播发送信息" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendOrderToXML"
android:text="给静态注册的广播接收者发送有序广播信息" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendOrderToJava"
android:text="给动态注册的广播接收者发送有序广播信息" />
</LinearLayout>
根据上面按钮的命名,应该知道这些按钮要发送的广播类型!
5.MainActivity.java文件的设计代码
package com.lwz.receiver;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
/**
* 本类用来发送广播
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//给静态广播发送信息
public void sendToSXL(View view) {
//发送广播使用sendBroadcast,需要指定Intent的action来说明发送什么样的广播。
//Intent里面的参数是action,要和静态注册的广播的actin对应
Intent intent = new Intent("myBroadcastReceiver");
intent.putExtra("msg", "这是MainActivity页面发送的广播----》》");
sendBroadcast(intent);
}
//给动态广播发送信息
public void sendToJava(View view) {
//发送广播使用sendBroadcast,需要指定Intent的action来说明发送什么样的广播。
//Intent里面的参数是action,要和动态注册的广播的actin对应
Intent intent = new Intent("javaReceiver");
intent.putExtra("msg", "这是MainActivity页面发送的广播----》》");
sendBroadcast(intent);
}
//给静态注册的广播发送有序广播信息
public void sendOrderToXML(View view) {
//发送有序广播使用sendOrderedBroadcast,需要指定Intent的action来说明发送什么样的广播。
//Intent里面的参数是action,要和静态注册的广播的actin对应
Intent intent = new Intent("myBroadcastReceiver");
intent.putExtra("msg", "这是MainActivity页面发送的广播----》》");
sendOrderedBroadcast(intent,null);
}
//给静态注册的广播发送有序广播信息
public void sendOrderToJava(View view) {
//发送广播使用sendOrderedBroadcast,需要指定Intent的action来说明发送什么样的广播。
//Intent里面的参数是action,要和静态注册的广播的actin对应
Intent intent = new Intent("javaReceiver");
intent.putExtra("msg", "这是MainActivity页面发送的广播----》》");
sendOrderedBroadcast(intent,null);
}
}
上面主要负责广播发送代码的设计。如果要发送的广播是没有对应的广播接收者,程序不会报错,只是会没有反应而已。
上面程序其实已经可以运行了,可以对静态的广播接收者发送广播。
如果是发送无序广播,两个广播接收者都会有消息,但是会出现错误报告!告诉你无序广播不能截断。
如果是发送有序广播,那么低优先级的广播不能接收广播数据。因为这里使用了拦截的方法!
(二)程序二的设计:
动态广播接收者的测试
1.第一个广播接收者的创建
package com.lwz.receiver2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* 这里使用动态的方法来创建一个广播接受者
* 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收!
*/
public class BroadcastReceiveForjava extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("Receiver", "这是使用动态的方法来创建的广播接受者1)----》" + intent.getStringExtra("msg"));
Toast.makeText(context, "这是使用动态的方法来创建的广播接受者1收到消息", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
2.第二个广播接收者的创建
package com.lwz.receiver2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* 这里使用动态的方法来创建一个广播接受者
* 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收!
*/
public class BroadcastReceiveForjava2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(“Receiver”, “这是使用动态的方法来创建的广播接受者2—-》” + intent.getStringExtra(“msg”));
Toast.makeText(context, “这是使用动态的方法来创建的广播接受者2收到消息”, Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
3.动态注册上面两个广播接收者
package com.lwz.receiver2;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
/**
* 这里使用动态的方法来创建一个广播接受者
* 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收!
* 动态广播的类创建之后要去使用代码注册才能生效
* 另外动态注册后要在某一个时间去解除绑定,否者会报错!
*/
public class MainActivity extends AppCompatActivity {
//定义广播接收者
BroadcastReceiveForjava receiver;
BroadcastReceiveForjava2 receiver2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建广播接收者对象
receiver = new BroadcastReceiveForjava();
receiver2 = new BroadcastReceiveForjava2();
//注册广播接收者,需要一个意图对象,也需要action参数,这里是定义Action参数
IntentFilter filter = new IntentFilter("javaReceiver");
IntentFilter filter2 = new IntentFilter("javaReceiver");
//动态设置广播的优先级
filter.setPriority(999);
filter2.setPriority(10);
//注册广播,
// 动态广播拦截?先注册者先收到消息???
registerReceiver(receiver2, filter);
registerReceiver(receiver, filter);
}
@Override
protected void onDestroy() {
//在适当的时候要解除广播接收者的绑定
unregisterReceiver(receiver);
unregisterReceiver(receiver2);
super.onDestroy();
}
}
程序二运行后,界面并没有画面。因为布局文件并没有设计。
这时不要退出程序二,点击回到主页,就可以再次进入程序一的界面,验证广播的接收和发送的效果。
程序运行后:
点击第一个按钮,对静态注册的广播接收者发送的无序广播,Log信息如下:
可以看到两个广播接收者都收到能收到广播的信息,只是报了一个错误给你!告诉你不能拦截无序的广播。 点击第三个按钮,对静态注册的广播接收者发送有序广播,Log信息如下:
可以看到成有序广播可以被截断,低等级的广播接收者不能收到被截断的广播。 点击第二个按钮,对动态注册的广播接收者发送无序广播,Log信息如下:
可以看到两个动态注册的广播接收者都可以接收到这个无序的广播。但是也是有报错!告诉你不能拦截无序广播哦。 点击第四个按钮,对动态注册的广播接收者发送有序广播,Log的信息如下:
可以看到有序广播可以被优先级高的动态广播接收者截断。
后面可以改变优先级来看看优先级是否起到作用!
从上面程序说明:无序广播不能截断,有序广播能被高优先级的广播接收者截断。不管是对静态的广播接收者还是对动态的广播接收者都是一样的。
四.接收手机短信广播信息的一个示例
(一)创建广播接收者
package com.lwz.phoneData;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 创建一个短信拦截广播接收者
*/
public class SMSBroadcastReceiver extends BroadcastReceiver {
private static final String action = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(action)) {
Object[] pduses = (Object[]) intent.getExtras().get("pdus");
String mobile = "";
String content = "";
String time = "";
System.out.println(pduses.length);
for (Object pdus : pduses) {
byte[] pdusmessage = (byte[]) pdus;
SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);
mobile = sms.getOriginatingAddress();// 发送短信的手机号码
content = sms.getMessageBody(); // 短信内容
Date date = new Date(sms.getTimestampMillis());// 发送日 期
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
time = format.format(date); // 得到发送时间
}
Toast.makeText(context, context.getResources().getString(R.string.app_name), Toast.LENGTH_LONG).show();
String show = "发送者:" + mobile + " 内容:" + content + " 时间:" + time;
Toast.makeText(context, show, Toast.LENGTH_LONG).show();
}
Log.e("TAG","拦截短信");
abortBroadcast();
}
}
(二)在AndroidManifest中注册
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter android:priority="1001">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
这里action的属性值必须正确,否则不能监听到这个广播!
这里还要添加手机权限:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
上面代码完成后就可以运行程序了,虽然界面没有设计布局,但是短信消息过来后,会有吐司出现。
五.系统广播定义的一些action值展示:
1.Intent.ACTION_AIRPLANE_M;
关闭或打开飞行模式时的广播
2.Intent.ACTION_BATTERY_CH;
(1)充电状态,或者电池的电量发生变化;
(2)电池的充电状态、电荷级别改变,不能通过组建声;
3.Intent.ACTION_AIRPLANE_MODE_CHANGED;
关闭或打开飞行模式时的广播
4.Intent.ACTION_BATTERY_CHANGED;
(1)充电状态,或者电池的电量发生变化
(2)电池的充电状态、电荷级别改变,不能通过组建声明 接收这个广播,只有通过registerReceiver()注册
5.Intent.ACTION_BATTERY_LOW;
表示电池电量低
6 .Intent.ACTION_BATTERY_OKAY;
表示电池电量充足,即从电池电量低变化到饱满时会发出广播
7.Intent.ACTION_BOOT_COMPLETED;
在系统启动完成后的广播,这个动作被广播一次(只有一次)。
8.Intent.ACTION_CAMERA_BUTTON;
按下照相时的拍照按键(硬件按键)时发出的广播
9.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息
10.Intent.ACTION_CONFIGURATION_CHANGED;
设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
11.Intent.ACTION_DATE_CHANGED;
设备日期发生改变时会发出此广播
12.Intent.ACTION_DEVICE_STORAGE_LOW;
设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用
13.Intent.ACTION_DEVICE_STORAGE_OK;
设备内存从不足到充足时发出的广播,此广播 只能由系统使用,其它APP不可用
14.Intent.ACTION_DOCK_EVENT;
发出此广播的地方
frameworks\base\services\java\com\android\server\DockObserver.java
15.Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
移动APP完成之后,发出的广播(移动是指:APP2SD)
16.Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
正在移动APP时,发出的广播(移动是指:APP2SD) 17.
17.Intent.ACTION_GTALK_SERVICE_CONNECTED;
Gtalk已建立连接时发出的广播
18.Intent.ACTION_GTALK_SERVICE_DISCONNECTED;
Gtalk已断开连接时发出的广播
19.Intent.ACTION_HEADSET_PLUG;
在耳机口上插入耳机时发出的广播
20.Intent.ACTION_INPUT_METHOD_CHANGED;
改变输入法时发出的广播
21.Intent.ACTION_LOCALE_CHANGED;
设备当前区域设置已更改时发出的广播
22.Intent.ACTION_MANAGE_PACKAGE_STORAGE;
表示用户和包管理所承认的低内存状态通知应该开始。
23. Intent.ACTION_MEDIA_BAD_REMOVAL;
未正确移除SD卡(正确移除SD卡的方法:设置–SD卡和设备内存–卸载SD卡),但已把SD卡取出来时发出的广播 ,扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mountpoint) 还没解除 (unmount)
24.Intent.ACTION_MEDIA_BUTTON;
按下”Media Button” 按键时发出的广播,假如有”Media Button” 按键的话(硬件按键)
25. Intent.ACTION_MEDIA_CHECKING;
插入外部储存装置,比如SD卡时,系统会检验SD卡,此时发出的广播。
26.Intent.ACTION_MEDIA_EJECT;
已拔掉外部大容量储存设备发出的广播(比如SD卡,或移动硬盘),不管有没有正确卸载都会发出此广播, 用户想要移除扩展介质(拔掉扩展卡)。
27.Intent.ACTION_MEDIA_MOUNTED;
插入SD卡并且已正确安装(识别)时发出的广播, 扩展介质被插入,而且已经被挂载。
28.Intent.ACTION_MEDIA_NOFS;
拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域。
29. Intent.ACTION_MEDIA_REMOVED;
外部储存设备已被移除,不管有没正确卸载,都会发出此广播, 扩展介质被移除。
30.Intent.ACTION_MEDIA_SCANNER_FINISHED;
广播:已经扫描完介质的一个目录
31.Intent.ACTION_MEDIA_SCANNER_SCAN_FILE;
请求媒体扫描仪扫描文件并将其添加到媒体数据库。
32.Intent.ACTION_MEDIA_SCANNER_STARTED;
广播:开始扫描介质的一个目录
33. Intent.ACTION_MEDIA_SHARED;
广播:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
34.Intent.ACTION_MEDIA_UNMOUNTABLE;
35.Intent.ACTION_MEDIA_UNMOUNTED
广播:扩展介质存在,但是还没有被挂载 (mount)
36.Intent.ACTION_NEW_OUTGOING_CALL;
37. Intent.ACTION_PACKAGE_ADDED;
(1)成功的安装APK之后
(2)广播:设备上新安装了一个应用程序包。
(3)一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
38.Intent.ACTION_PACKAGE_CHANGED;
一个已存在的应用程序包已经改变,包括包名
39.Intent.ACTION_PACKAGE_DATA_CLEARED;
(1)清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,之后点清除数据时?)
(2)用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播)
40.Intent.ACTION_PACKAGE_INSTALL;
触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用?
41.Intent.ACTION_PACKAGE_REMOVED;
成功的删除某个APK之后发出的广播, 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
42.Intent.ACTION_PACKAGE_REPLACED;
替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播?)
43.Intent.ACTION_PACKAGE_RESTARTED;
用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
44.Intent.ACTION_POWER_CONNECTED;
插上外部电源时发出的广播
45.Intent.ACTION_POWER_DISCONNECTED;
已断开外部电源连接时发出的广播
46.Intent.ACTION_PROVIDER_CHANGED;
47.Intent.ACTION_REBOOT;
重启设备时的广播
48.Intent.ACTION_SCREEN_OFF;
屏幕被关闭之后的广播
49. Intent.ACTION_SCREEN_ON;
屏幕被打开之后的广播
50.Intent.ACTION_SHUTDOWN;
关闭系统时发出的广播
51. Intent.ACTION_TIMEZONE_CHANGED;
时区发生改变时发出的广播
52.Intent.ACTION_TIME_CHANGED;
时间被设置时发出的广播
53.Intent.ACTION_TIME_TICK;
广播:当前时间已经变化(正常的时间流逝), 当前时间改变,每分钟都发送,不能通过组件声明来接收 ,只有通过Context.registerReceiver()方法来注册
54. Intent.ACTION_UID_REMOVED;
一个用户ID已经从系统中移除发出的广播
55. Intent.ACTION_UMS_CONNECTED;
设备已进入USB大容量储存状态时发出的广播?
56.Intent.ACTION_UMS_DISCONNECTED;
设备已从USB大容量储存状态转为正常状态时发出的广播?
57.Intent.ACTION_USER_PRESENT;
58.Intent.ACTION_WALLPAPER_CHANGED;
设备墙纸已改变时发出的广播
上面这些广播是系统在某个阶段会自动发出的,你只需要定义好广播接收者,并设置对应的action属性值,就可以在你一个阶段下收到到它们的广播信息。
六.广播接收者BroadcastReceiver总结
发送频率低的可以使用 数据量小在可使用 intent携带的数据不能太大 广播的操作一定要在5秒钟内完成(10秒不能完成,ANR),如果耗时时间太长,开启服务。
(一)两种注册方法
1. 静态注册,manifest文件中注册,广播应该是一个外部类
优点:程序不启动,一样能收到广播,一般用于推送(自己搭建)。系统的处理。
缺点:占用资源较多。只有广播,系统会去匹配所有的接受者。
2.动态注册 一般都是匿名类代码中通过Content的方法 registerReceiver(receiver,intentfilter)注册广播; 在退出的时候一定需要解绑,否则抛异常。unRegisterReceiver 用于程序组件之间的消息传递。需要刷新UI
优点:程序占用资源少,及时释放
缺点:一定需要组件启动,注册广播。
(二)发送广播
两种发送方法
1.无序广播 消息同时到达,不能延迟 sendBroadcast(Intent);
2. 有序广播
消息按照优先级来传递,可以延迟,并且可以拦截 sendOrderedBroadcast(Intent,permission); permission可以为null,表明不需要额外的权限,如果不为空,所有接收方必须有这个权限。
拦截方法 abortBroadcast();
广播优先级,应该是有序广播才能有效果;
广播最大的作用 Activity与Service进行通信 MyApp通知所有的界面。
其中广播的静态广播和动态广播,有序广播和无序广播。这个需要我们有比较清楚的思路。
静态广播和动态广播指的是广播接受者注册方式,静态广播接收者是在AndroidManifest中用xml语句设置;动态广播接收者是在某个java文件中使用java代码注册。
有序广播和无序广播指的是发送广播的方式:根据广播接收者的优先级来确定哪一个广播接收者先获得广播,无序广播不能被拦截,有序广播会可以被拦截。
所以说动态和静态是对广播接收者的描述;
有序和无序是是对发送的广播本身的描述。