四大组件之BroadcastReceiver

    学之广在于不倦,不倦在于固志。 ——晋·葛洪­

   (学问的渊博在于学习时不知道厌倦,而学习不知厌倦在于有坚定的目标)


    001.BroadcastReceiver简介:

        广播接收者,安卓四大组件之一,在安卓领域有着广泛的应用,比如:

            系统开机广播:

                当开机完成之后系统会发送一条广播,接收到这条广播就能实现开机启动服务的功能

            电量变化广播:

                当电池电量发生改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度

            网络变化广播:

                当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作

            强制下线广播:

                当我们的账户被他人登录时,服务端就会推送一条广播,我们接收到这个广播就会强制用户下线重新登录

            等等,还有很多的广播

        Android中广播主要分为标准广播有序广播:

            标准广播:

                    --> 是一种完全异步的广播,在广播发出去之后,所有的广播接收者几乎在同一时间接收到这条广播,因此它们之间没有先后顺序

                    --> 发送方式:sendBroadcast();

                    --> 优点是效率比较高效

                   --> 缺点是无法控制、修改

            有序广播:

                   --> 是一种同步执行的广播,在广播发出去之后,同一时刻只会有一个广播接收者能够接收到这条广播,当这个广播接收器中的逻辑执行完毕之后,广播才会继续传递

                   --> 发送方式:sendOrderBroadcast();

                   --> 优点有先后顺序,优先级(priority属性来设置优先级,范围-1000~1000)高的广播接收器先接收到,可以对接收到的广播进行截断、编辑修改


        注意:

            广播还有其他类型,比如:

                系统广播(System Broadcast):

                     --> 只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播

                     --> 每个广播都有特定的Intent - Filter(包含具体的action),具体请点击此处参考

                     --> 当使用系统广播时,只需要在清单文件注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播,只需要创建广播接收者进行相关操作即可

                粘性广播(Sticky Broadcast):

                     --> 由于在Android5.0 & API 21中已经失效,所以不建议使用

                本地广播(Local Broadcast):

                     --> 可理解为一种局部广播,广播的发送者和接收者都同属于一个App,使用这种机制发出的广播只能够在应用程序内部进行传递

                     --> 相比于全局广播(上面的几种),本地广播优势体现在:安全性高 & 效率高

                     --> 本地广播无法通过静态注册方式来接收                


    002.广播的具体使用及代码实战:

       实现步骤:

           0a、创建广播接收者

              --> 新建一个类,让它继承BroadcastReceiver并重写父类的onReceiver()方法

               --> 当有广播到来时,onReceiver()方法就会执行,具体的逻辑就可以在该方法中进行

           0c、注册广播

               --> 分为动态注册和静态注册(具体看下面代码)

               --> 两者区别:

                       动态注册属于非常驻型广播,比较灵活,生命跟随所注册的组件,组件退出广播退出,在退出广播时必须移除广播接收者,否则会造成内存泄漏,必须在程序启动后才能接收到广播

                       静态注册属于常驻型广播,不受任何组件的生命周期影响,在应用关闭之后,若有广播来临也可以接收广播,耗电、占内存

              --> 注意,广播的注册和取消建议在onResume和onPause,因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露

           0b、发送广播

               -->标准及其他广播使用:sendBroadcast()

               -->有序广播使用:sendOrderBroadcast()

       代码实战:    

           0a、标准广播:点击按钮发送广播,收到广播弹出提示

       1> 动态注册广播

public class MainActivity extends AppCompatActivity {
    private IntentFilter mFilter;
    private MyBroadcastReceiver mReceiver;
    private static final String MYBROADCAST_ACTION = "com.example.mycast.MyBroadcastReceiver";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //点击按钮发送广播
        findViewById(R.id.bt_register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MYBROADCAST_ACTION);
                sendBroadcast(intent);
            }
        });
    }

    /**
     * 动态注册广播
     */
    @Override
    protected void onResume() {
        super.onResume();
        //构建IntentFilter并添加Action
        mFilter = new IntentFilter();
        //接收的广播类型
        mFilter.addAction(MYBROADCAST_ACTION);
        //创建广播接受者
        mReceiver = new MyBroadcastReceiver();
        //注册广播
        registerReceiver(mReceiver, mFilter);
    }

    /**
     * 标准广播接收者:当有匹配的广播到来时,onReceiver()方法就会执行,具体信息
     * 保存在Intent中,具体得到处理就需要在此方法中进行
     */
    class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received in MyBroadcastReceiver!", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 动态注册的广播一定要移除广播接收者
     */
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }
} 

      2>静态注册广播

清单文件注册

<receiver android:name=".MainActivity$MyBroadcastReceiver">
    <intent-filter>
        <action android:name="com.example.mycast.MyBroadcastReceiver"/>
    </intent-filter>
</receiver>

public class MainActivity extends AppCompatActivity {
    private static final String MYBROADCAST_ACTION = "com.example.mycast.MyBroadcastReceiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //点击按钮发送广播
        findViewById(R.id.bt_register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MYBROADCAST_ACTION);
                sendBroadcast(intent);
            }
        });
    }

    /**
     * 标准广播接收者:当有匹配的广播到来时,onReceiver()方法就会执行,具体信息
     * 保存在Intent中,具体得到处理就需要在此方法中进行
     */
    public static class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received in MyBroadcastReceiver!", Toast.LENGTH_LONG).show();
        }
    }
} 

           0b、有序广播:点击项目的发送,进行信息的修改,后续广播发生变化

项目1,设置优先级为100

<receiver android:name=".MainActivity$MyBroadcastReceiver">
    <intent-filter android:priority="100">
        <action android:name="com.example.mycast.MyBroadcastReceiver"/>
    </intent-filter>
</receiver>

public class MainActivity extends AppCompatActivity {
    private static final String MYBROADCAST_ACTION = "com.example.mycast.MyBroadcastReceiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //点击按钮发送有序广播
        findViewById(R.id.bt_register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MYBROADCAST_ACTION);
                intent.putExtra("msg", " One Message Send!!");
                sendOrderedBroadcast(intent, null);
            }
        });
    }

    /**
     * 标准广播接收者:当有匹配的广播到来时,onReceiver()方法就会执行,具体信息
     * 保存在Intent中,具体得到处理就需要在此方法中进行
     */
    public static class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(MYBROADCAST_ACTION)) {
                String msg = intent.getStringExtra("msg");
                //显示我们传递的信息
                Toast.makeText(context, "Received in MyBroadcastReceiver!" + msg, Toast.LENGTH_SHORT).show();
                //有序广播进行信息的修改
                Bundle extras = new Bundle();
                extras.putString("msg", msg+"已经过加工");
                //继续向下传
                setResultExtras(extras);
            }
        }
    }

项目2,设置优先级为99

<receiver android:name=".AnotherBroadcastReceiver">
    <intent-filter android:priority="99">
        <action android:name="com.example.mycast.MyBroadcastReceiver"/>
    </intent-filter>
</receiver>

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
public class AnotherBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("com.example.mycast.MyBroadcastReceiver")) {
            //获取广播的原始信息
            String msg = intent.getStringExtra("msg");
            //获取广播经过修改的信息
            Bundle bundle = getResultExtras(true);
            String change = bundle.getString("msg");
            //显示2种信息
            Toast.makeText(context, "Received in AnotherBroadcastReceiver!" + change + "," + msg, Toast.LENGTH_SHORT).show();
        }
    }
}

           0c、系统广播:动态注册系统网络状态变化广播

广播接收者

/**
 * 接收广播:当有匹配的广播到来时,onReceiver()方法就会执行,具体信息
 * 保存在Intent中,具体得到处理就需要在此方法中进行
 */
class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        //ConnectivityManager: 系统用于管理网络连接的服务类
        ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();

        //通过NetworkInfoisAvailable()方法判断当前是否有网络,并提示信息
        if (null != info && info.isAvailable()) {
            Toast.makeText(context, "Network is Available !!", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(context, "Network is unAvailable !!", Toast.LENGTH_LONG).show();
        }
    }
}

动态广播注册(因为是系统广播会自动发送广播)

private IntentFilter mFilter;
private NetworkReceiver mReceiver;
private static final String NETWORK_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";

/**
*
动态注册广播
*/
@Override
protected void onResume() {
super.onResume();
//构建IntentFilter并添加Action
mFilter = new IntentFilter();
mFilter.addAction(NETWORK_ACTION);
//创建广播接受者
mReceiver = new NetworkReceiver();
//注册广播
registerReceiver(mReceiver, mFilter);
}

注意需要在清单文件配置:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

当系统的网络状况发生改变时,就会提示相应的变化


           0d、系统广播:静态注册开机广播

广播接收者

/**
 * 监听开机广播
 */
public static class BootCompleteReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Toast.makeText(context, "Boot Completed !!", Toast.LENGTH_LONG).show();
    }
}

静态注册系统广播

<receiver android:name=".MainActivity$BootCompleteReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
相关权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

在模拟机开机后,会弹出提示“Boot Completed !!”广播


             0e、本地广播:

/**
 * 本地广播安全、高效,属于局部广播,在App内部才有效
 */
public class MainActivity extends AppCompatActivity {
    private LocalBroadcastManager mLocalBroadcastManager;
    private LocalReceiver mLocalReceiver;
    private IntentFilter mFilter;
    private static final String LOCAL_ACTION = "com.test.okamiy.broadcast.LOCAL_BROADCAST";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //点击发送本地广播
        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(LOCAL_ACTION);
                //发送广播
                mLocalBroadcastManager.sendBroadcast(intent);
            }
        });
    }

    /**
     * 广播接收者
     */
    class LocalReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received Local Broadcast!", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 注册本地广播
     */
    @Override
    protected void onResume() {
        super.onResume();

        //获取本地广播实例,用来注册和发送广播
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(MainActivity.this);
        mFilter = new IntentFilter();
        mFilter.addAction(LOCAL_ACTION);
        mLocalReceiver = new LocalReceiver();
        //注册本地广播
        mLocalBroadcastManager.registerReceiver(mLocalReceiver, mFilter);
    }

    /**
     * 一定记得取消注册
     */
    @Override
    protected void onPause() {
        super.onPause();
        mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
    }
}

          003.总结:

              --> BroadcastReceiver里面的onReceiver()方法中不能添加过多的逻辑或者耗时操作,因为广播接收者是不允许开线程的,但是可以在里面开起服务执行耗时操作,因此广播接收者更多是扮演打开程序其他组件的角色,比如创建一条状态栏通知、启动一个服务

              --> 对于不同注册方式的广播接收者回调onReceive(Context context,Intent intent)中的context返回值是不一样的:

                 1>.对于静态注册(全局+应用内广播),回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;

                 2>.对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:Activity Context;

                 3>.对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Application Context;

                 4>.对于应用内广播的动态注册(非LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Activity Context;


          004.个人总结可能有错误,欢迎指正探讨,参照博文:

                 a、传送门 :优快云--细节篇,一篇就够了

                 b、传送门 :简书--相对比较好的一篇

 

          Last:欢迎探讨学习


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值