zoukankan      html  css  js  c++  java
  • 四大组件之BroadcastReceiver基础

    1. 系统广播

    1.1 动态注册

      (1)创建自定义接收器类继承自BroadcaseReceiver,实现onReceive()方法,对接收到的广播的逻辑处理就是写在这个函数中的。

      (2)实例化IntentFilter对象,并通过addAction()方法加入需要接收的广播值。使用系统广播时可查阅官方文档,找到需要的Action。

      (3)实例化自定义接收器类的对象,并通过registerReceiver()方法注册接收器对象。

      (4)在AndroidManifest.xml文件中,通过uses=permission标签进行权限声明。若非系统的关键性信息,则无需这一步。

      (5)使用完后,动态注册的广播接收器一定要通过unregisterReceiver()方法取消注册。

    范例: 监测当前网络状态,若断网,则提示用户当前网络不可用。

    AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.studying.myapplication">
    
        <!--声明权限-->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".BroadcaseActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    活动类:

    public class BroadcaseActivity extends Activity {
    
        private IntentFilter mFilter;
        private NetworkChangeReceiver mReceiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcase);
    
            //实例化IntentFilter对象,并加入Action
            mFilter = new IntentFilter();
            mFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            mReceiver = new NetworkChangeReceiver();
            //注册接收器
            registerReceiver(mReceiver, mFilter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //动态注册的广播接收器一定要取消注册
            unregisterReceiver(mReceiver);
        }
    
        class NetworkChangeReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                //获取网络状态信息
                ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    
                //当网络信息对象为空或者网络不可用时,提示用户
                if (networkInfo == null || !networkInfo.isAvailable()) {
                    Toast.makeText(context, "Network is unavailable.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

    1.2 静态注册

      相对动态注册而言,静态注册接收器非常简单,只需要自定义一个接收器类,而后实现onReceive()方法,在里面实现对广播的处理,然后在AndroidManifest.xml文件中通过receiver标签进行注册即可。需要注意,无论是静态注册还是动态注册,如果需要访问系统的关键性信息,都必须在配置文件中声明权限。

    范例: 静态注册实现开机自启。

    AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.studying.myapplication">
    
        <!--声明权限-->
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
    
            <!--通过receiver标签静态注册-->
            <receiver android:name=".BootCompleteReceiver" >
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                </intent-filter>
            </receiver>
    
            <activity android:name=".BroadcaseActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    自定义接收器类:

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

    2. 自定义广播

    2.1 标准广播

      自定义广播的接收方法与系统广播的一样,也有静态注册和动态注册两种方法,这里就不再赘述。

      自定义广播的不同之处在于,它是手动发送的,方法是新建一个Intent对象并加入自定义的广播值,而后通过sendBroadcase()方法发送,此时发送出去的就是一条标准广播。

    范例: 发送一条自定义标准广播并接收。

    AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.studying.myapplication">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
    
            <!--通过receiver标签静态注册-->
            <receiver android:name=".MyReceiver" >
                <intent-filter>
                    <action android:name="com.studying.MyBroadcast" />
                </intent-filter>
            </receiver>
    
            <activity android:name=".BroadcaseActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    自定义接收器类:

    public class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received.", Toast.LENGTH_SHORT).show();
        }
    }
    

    布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.studying.myapplication.BroadcaseActivity">
    
        <Button
            android:id="@+id/send"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:text="Send MyBroadcase" />
    </LinearLayout>
    

    活动类:

    public class BroadcaseActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcase);
    
            Button send = (Button) findViewById(R.id.send);
            send.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //实例化一个Intent对象,并发送广播
                    Intent intent = new Intent("com.studying.MyBroadcast");
                    sendBroadcast(intent);
                }
            });
        }
    }
    

    2.2 有序广播

      与标准广播不同之处在于,标准广播是异步执行的,所有广播接收器会在同一时刻接收到;而有序广播是同步执行的,同一时刻只会有一个接收器收到,当这个接收器里面的逻辑执行完毕后,广播才会继续传播。

      因此,有序广播有两个要点,第一,优先级高的接收器可以先收到广播,优先级高低通过priority给定;第二,前面的接收器可以截断,让后面的接收器无法收到广播,这个则是通过abortBroadcase()方法实现。

      此外,有序广播是通过sendOrderedBroadcase()方法进行发送的。

    范例: 创建两个自定义广播类,并且让MyReceiver1的优先级高于MyReceiver2,而后在MyReceiver1中调用abortBroadcase()方法截断广播的传递。

    AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.studying.myapplication">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
    
            <!--使MyReceiver1的优先级高于MyReceiver2的-->
            <receiver android:name=".MyReceiver1" >
                <intent-filter android:priority="100">
                    <action android:name="com.studying.MyBroadcast" />
                </intent-filter>
            </receiver>
            <receiver android:name=".MyReceiver2" >
                <intent-filter android:priority="50">
                    <action android:name="com.studying.MyBroadcast" />
                </intent-filter>
            </receiver>
    
            <activity android:name=".BroadcaseActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    布局文件与标准广播的范例一样:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.studying.myapplication.BroadcaseActivity">
    
        <Button
            android:id="@+id/send"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:text="Send MyBroadcase" />
    </LinearLayout>
    

    活动类:

    public class BroadcaseActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcase);
    
            Button send = (Button) findViewById(R.id.send);
            send.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //发送有序广播
                    Intent intent = new Intent("com.studying.MyBroadcast");
                    sendOrderedBroadcast(intent, null);
                }
            });
        }
    }
    

    MyReceiver1:

    public class MyReceiver1 extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received in MyReceiver1.", Toast.LENGTH_SHORT).show();
            abortBroadcast();
        }
    }
    

    MyReceiver2:

    public class MyReceiver2 extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Received in MyReceiver2.", Toast.LENGTH_SHORT).show();
        }
    }
    

      若把MyReceiver1中的abortBroadcase();这一句注释掉,点击发送则可一次看到两个接收器的提示。

    3. 本地广播

      本地广播只能够在应用程序内部进行传递,广播接收器也只能接收本程序发出的广播,这样的机制解决了全局广播可能出现的安全问题。

      使用本地广播非常简单,与全局广播不一样的地方在于,使用了一个LocalBroadcastManager对广播进行管理,使用这个管理器发送的广播以及注册的接收器,即为本地广播和本地广播接收器。

      另外,由于发送本地广播时,程序必定处于启动状态,因而不需要并且也没有静态注册。

    范例: 发送一条本地广播并接收。

    活动类:

    public class BroadcaseActivity extends Activity {
    
        private MyReceiver mReceiver;
        private LocalBroadcastManager mManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcase);
    
            //获取本地广播管理器
            mManager = LocalBroadcastManager.getInstance(this);
    
            Button send = (Button) findViewById(R.id.send);
            send.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //通过本地广播管理器发送广播
                    Intent intent = new Intent("com.studying.MyLocalBroadcast");
                    mManager.sendBroadcast(intent);
                }
            });
    
            //通过本地广播管理器进行动态注册
            IntentFilter mFilter = new IntentFilter();
            mFilter.addAction("com.studying.MyLocalBroadcast");
            mReceiver = new MyReceiver();
            mManager.registerReceiver(mReceiver, mFilter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //通过本地广播管理器取消注册
            mManager.unregisterReceiver(mReceiver);
        }
    
        //自定义接收器类
        class MyReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "Received.", Toast.LENGTH_SHORT).show();
            }
        }
    }
    

      最后,在使用广播接收器时要注意,不要在onReceive()方法中加任何耗时操作,广播接收器更多的是接收某些广播讯息,从而开启其它组件。在广播接收器中是不允许开启线程的,当onReceive()方法运行了长时间仍未结束时,程序就会报错。

  • 相关阅读:
    安装MySQL
    Apache安装与重启、启动失败
    MySQL重启
    数据库查询乱码
    MySQL数据表操作、查看mysql表的信息等
    rust学习之一:基本语法
    llvm clang的编译和安装
    Linux 性能分析60秒初步排除手段
    pahole编译过程libbpf: failed to find valid kernel BTF
    ipmitool常用指令测试大全
  • 原文地址:https://www.cnblogs.com/joahyau/p/6714558.html
Copyright © 2011-2022 走看看