• 从0系统学Android--5.1 广播机制


    从0系统学Android--5.1 广播机制


    本系列文章目录更多精品文章分类

    本系列持续更新中.... 初级阶段内容参考《第一行代码》

    第五章:全局大喇叭---详解广播机制

    5.1 广播机制简介

    Android 中每个应用程序都可以对自己感兴趣的广播进行注册,这样当注册的广播发出时,应用程序就会接受到。这些广播可能来自系统,也可能来自其他应用程序。

    接受广播需要用到Broadcast Receiver 广播接收器。

    Android 中的广播分为两种:标准广播和有序广播

    标准广播:是一种完全异步执行的广播,在广播发出后几乎所有的接收器都会在同一时刻受到广播消息。因此它们之间没有任何的先后顺序,这种广播效率比较高,但同时意味着不能被截断。

    有序广播:是一种同步执行的广播,在广播发出后,同一时刻只有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后广播才会继续传播。有序广播是有先后顺序的,优先级高的会优先接受到广播并且可以截断正在传递的广播。

    5.2 接受系统广播

    Android 系统内置了许多的系统级别的广播,我们可以通过这些广播来获取手机的一些状态。比如手机开机会发送一条广播,电池电量发生变化会发送广播,时间或者时区发生改变会发送广播等等。

    5.2.1 动态注册监听网络变化

    注册广播的方式有两种:一种是在代码中注册称为动态注册,另一种是在 AndroidManifest.xml 中注册称为静态注册

    如何才能接受到广播呢?首先要创建一个广播接收器。

    新建一个类,让他继承 BoradcastReceiver 并重写 onReceive() 方法,当接受到广播后就会执行 onReceive() 方法,这样一个简单的广播包接收器就创建好了。

    下面来具体实践一下:

    public class NetChangeActivity extends AppCompatActivity {
        NetWorkChangeReceiver netWorkChangeReceiver;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_ui);
            IntentFilter intentFilter = new IntentFilter();
     // 每当网络状态发生改变的时候都会接受到广播(有网络了,没有网络了,切换到 WiFi了)   
          intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            netWorkChangeReceiver = new NetWorkChangeReceiver();
            registerReceiver(netWorkChangeReceiver,intentFilter);
        }
    
        class NetWorkChangeReceiver extends BroadcastReceiver{
    
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context,"网络状态发生变化",Toast.LENGTH_SHORT).show();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(netWorkChangeReceiver);
        }
    }
    

    其实具体过程很简单,步骤:

    1. 新建一个广播接收器
    2. 通过 IntentFilter 来指定要接受的广播
    3. registerReceiver() 来注册广播
    4. 需要取消注册

    进一步编写,告诉用户当前是有网络还是没有网络

      ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
                if (networkInfo!=null && networkInfo.isAvailable()){
                    Toast.makeText(context,"网络可用",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(context,"网络不可用",Toast.LENGTH_SHORT).show();
                }
    

    主要是通过 ConnectivityManager 这个专门用于管理网络的服务类来实现的。

    注意这里需要访问系统的网络状态,需要声明权限,在 AndroidManifest.xml

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

    5.2.2 静态注册实现开机启动

    动态注册广播接受有一个缺点就是必须程序运行了才可以接受到广播,原因很简单,只有我们打开了对应的程序页面运行了注册的逻辑才可以接受到广播。

    那么怎么样可以让程序在没有启动的情况下就能接受到广播呢?这就需要静态注册了。

    静态注册可以让程序没有启动就接受到广播消息

    代码实现:首先我们新建一个 Java 类继承自 BroadcastReceiver

    public class BootCompleteReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context,"开机完成",Toast.LENGTH_SHORT).show();
        }
    }
    
    

    很简单,当接收到开机广播后就Toast 一下就可以了。下面开始进行静态注册,到 AndroidManifest.xml 中,其实和注册 Activity 非常相似

       <receiver android:name="com.example.firstcode.fifty_chapter.bootreceiver.BootCompleteReceiver"
         				android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED"/>
                </intent-filter>
            </receiver>
    

    重点是 exported 设置为 true 表示可以接受本程序之外的广播,不然就接受不到程序外的广播了,因为要接受开机广播,不是我们的程序自己发出的所以要设置为 true 。enable 的意思就是启用这个广播接收器。

    通过 action 标签指定要接受的广播。接受开机广播需要权限

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

    好了,这样在开机的时候就会接受到广播了。

    注意: 广播接收器 onReceive() 方法里面不要做太多的逻辑或者任何的耗时操作,因为在广播接收器中是不允许开启线程的,并且如果 onReceive() 方法运行了较长时间而没有结束的话程序就会报错。因此广播接收器扮演的是一种打开程序其他组件的角色,比如创建状态栏通知,或者启动一个服务等等

  • 相关阅读:
    计算机编码规则之:Base64编码
    java高级用法之:在JNA中将本地方法映射到JAVA代码中
    java高级用法之:JNA类型映射应该注意的问题
    netty系列之:netty中的核心MessageToMessage编码器
    netty系列之:netty中的核心MessageToByte编码器
    ClickHouse遇到的一些配置导致的报错问题记录
    ClickHouse如何引用多个配置文件
    DM达梦数据库License的替换安装
    【高并发】不得不说的线程池与ThreadPoolExecutor类浅析
    【高并发】深度解析线程池中那些重要的顶层接口和抽象类
  • 原文地址:https://www.cnblogs.com/sydmobile/p/12450415.html
Copyright © 2020-2023  润新知