一.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();
    }
}

       程序二运行后,界面并没有画面。因为布局文件并没有设计。
       这时不要退出程序二,点击回到主页,就可以再次进入程序一的界面,验证广播的接收和发送的效果。
       程序运行后:

android 多个广播 android广播使用_android


       点击第一个按钮,对静态注册的广播接收者发送的无序广播,Log信息如下:

android 多个广播 android广播使用_android 多个广播_02


android 多个广播 android广播使用_优先级_03


       可以看到两个广播接收者都收到能收到广播的信息,只是报了一个错误给你!告诉你不能拦截无序的广播。       点击第三个按钮,对静态注册的广播接收者发送有序广播,Log信息如下:

android 多个广播 android广播使用_android 多个广播_04


       可以看到成有序广播可以被截断,低等级的广播接收者不能收到被截断的广播。       点击第二个按钮,对动态注册的广播接收者发送无序广播,Log信息如下:

android 多个广播 android广播使用_android_05


android 多个广播 android广播使用_广播接收者_06


       可以看到两个动态注册的广播接收者都可以接收到这个无序的广播。但是也是有报错!告诉你不能拦截无序广播哦。       点击第四个按钮,对动态注册的广播接收者发送有序广播,Log的信息如下:

android 多个广播 android广播使用_android_07


       可以看到有序广播可以被优先级高的动态广播接收者截断。

       后面可以改变优先级来看看优先级是否起到作用!

       从上面程序说明:无序广播不能截断,有序广播能被高优先级的广播接收者截断。不管是对静态的广播接收者还是对动态的广播接收者都是一样的。

四.接收手机短信广播信息的一个示例

(一)创建广播接收者

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代码注册。
       有序广播和无序广播指的是发送广播的方式:根据广播接收者的优先级来确定哪一个广播接收者先获得广播,无序广播不能被拦截,有序广播会可以被拦截。
       所以说动态和静态是对广播接收者的描述;
       有序和无序是是对发送的广播本身的描述。