zoukankan      html  css  js  c++  java
  • [Android基础]Android四大组件之BroadCast

    BroadCast的定义:

    广播是一种订阅--通知 事件,广播接收者向Android系统 register (订阅广播),广播发送者向Adnroid系统 sendBroadCast(发送广播),然后Android 系统通知所有注册该广播的接收者,广播接收者收到自己注册的广播之后实现自己想做的事情(该事情一般不超过10s,否则应用会出现ANR)。

    BroadCast的分类:

    1.无序广播:也就是普通广播,只要注册了该action的广播接收者都能收到该广播,且没有先后顺序。
    2.有序广播:广播接收者按照优先级高低依次接受该广播,并且优先接收的广播可以通过setResultExtras(Bundle)方法,将处理好的结果传送到下一个广播接收者那里。
    3.粘性广播:发送广播调用的方法 sendStickyBroadcast(Intent),和sendBroadcast(Intent)不同。
    粘性广播会一直保留在内存当中,直到有广播接收者注册该广播,该广播才算结束。不好解释,等会具体看例子。

    BroadCase的使用:

    一.普通广播

    根据注册方式不同可以分为 静态注册广播和动态注册广播。

    1.静态注册广播使用实例

    AndroidManifest.xml 如下:

    <?xml version="1.0" encoding="utf-8"?>  
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
        package="com.***.mybroadcast">  
      
        <application  
            android:allowBackup="true"  
            android:icon="@drawable/ic_launcher"  
            android:label="@string/app_name"  
            android:theme="@style/AppTheme">  
            <activity  
                android:name=".MainActivity"  
                android:label="@string/app_name">  
                <intent-filter>  
                    <action android:name="android.intent.action.MAIN" />  
      
                    <category android:name="android.intent.category.LAUNCHER" />  
                </intent-filter>  
            </activity>  
      
            <!--静态注册广播,此处需要添加广播的action-->  
            <receiver android:name=".BroadCastReceive1">  
                <intent-filter>  
                    <action android:name="com.***.mybroadcast.BroadCastReceive1"></action>  
                </intent-filter>  
            </receiver>  
        </application>  
      
    </manifest>  
    

    2.广播接收者实现如下:

    package com.***.mybroadcast;  
      
    import android.content.BroadcastReceiver;  
    import android.content.Context;  
    import android.content.Intent;  
     
      
    public class BroadCastReceive1 extends BroadcastReceiver {  
      
        @Override  
        public void onReceive(Context context, Intent intent) {  
            //TODO 接收到广播之后处理自己的事情  
            String action = intent.getAction();  
            String result = intent.getStringExtra("key");  
            MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
        }  
    }  
    
    

    3.广播发送者实现如下:

    package com.***.mybroadcast;  
      
    import android.content.Intent;  
    import android.os.Bundle;  
    import android.support.v7.app.ActionBarActivity;  
    import android.view.View;  
    import android.widget.Button;  
      
      
    public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
      
        private Button btnSend;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
      
            btnSend = (Button) findViewById(R.id.button);  
            btnSend.setOnClickListener(this);  
      
        }  
      
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
                case R.id.button:  
                    sendBraodCast();  
                    break;  
            }  
        }  
      
        private void sendBraodCast() {  
      
            /** 
             * 申明静态广播的 action 行为 
             */  
            String action = "com.***.mybroadcast.BroadCastReceive1";  
            Intent intent = new Intent(action);  
            intent.putExtra("key", "静态广播测试");  
            sendBroadcast(intent);  
        }  
    }  
    

    打印结果如下:

    4.静态注册广播特点:

    1.注册广播在 AndroidManifest.xml中。
    2.广播接收者需重新 继承 BroadcastReceiver 类来实现 onReceive()抽象方法。
    3.应用退出无需 注销广播,因此导致:即使广播退出之后,如果有其他应用发送该action行为的广播,此应用还是能接收到该广播的,也就是还会打印上面的 结果。

    二.动态广播:

    示例

    <pre name="code" class="java">package com.***.mybroadcast;  
      
    import android.content.BroadcastReceiver;  
    import android.content.Context;  
    import android.content.Intent;  
    import android.content.IntentFilter;  
    import android.os.Bundle;  
    import android.support.v4.content.LocalBroadcastManager;  
    import android.support.v7.app.ActionBarActivity;  
    import android.view.View;  
    import android.widget.Button;  
    
    public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
      
        private Button btnSend;  
      
        private BroadCastReceive2 myReceive;  
      
        private IntentFilter filter;  
      
        private final static String ACTION = "com.***.mybroadcast.BroadCastReceive2";  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
      
            btnSend = (Button) findViewById(R.id.button);  
            btnSend.setOnClickListener(this);  
      
            myReceive = new BroadCastReceive2();  
            filter = new IntentFilter();  
            filter.addAction(ACTION);  
      
        }  
      
      
        @Override  
        protected void onResume() {  
            /** 
             * 注册广播 
             */  
      
            LocalBroadcastManager.getInstance(this).registerReceiver(myReceive, filter);//官方建议使用  
      
    //        this.registerReceiver(myReceive, filter);  
      
            super.onResume();  
        }  
      
      
        @Override  
        protected void onPause() {  
            /** 
             * 注销广播 
             */  
      
            LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceive);//官方建议使用  
      
    //        this.unregisterReceiver(myReceive);  
      
            super.onPause();  
        }  
      
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
                case R.id.button:  
                    sendBraodCast();  
                    break;  
            }  
        }  
      
        private void sendBraodCast() {  
      
            /** 
             * 申明广播的 action 行为 
             */  
            Intent intent = new Intent(ACTION);  
            intent.putExtra("key", "动态广播测试");  
      
            /** 
             * 官方提倡使用如下发送广播,原因是更快,更安全,不会导致内存泄漏 
             */  
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);  
      
    //        this.sendBroadcast(intent);  
        }  
      
      
        /** 
         * 内部类实现广播接收器 
         */  
        private class BroadCastReceive2 extends BroadcastReceiver {  
      
            @Override  
            public void onReceive(Context context, Intent intent) {  
                //TODO 接收到广播之后处理自己的事情  
                String action = intent.getAction();  
                String result = intent.getStringExtra("key");  
                MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
            }  
        }  
    }  
    

    打印结果如下:

    动态广播特点:

    1.在代码中调用registerReceiver()方法 注册广播。
    2.广播接收者需重新 继承 BroadcastReceiver 类实现内部类。
    3.动态广播在应用退出时需要 调用unregisterReceiver()方法来注销广播。如果应用退出时没有注销广播,会报如下错误:

    因此,我们通常的做法是:在 onResume()中注册广播,在onPause中注销广播。
    4.当广播注销之后就接收不到任何系统发送的广播了。

    三.有序广播:

    示例:

    <pre name="code" class="java">package com.***.mybroadcast;  
      
    import android.content.BroadcastReceiver;  
    import android.content.Context;  
    import android.content.Intent;  
    import android.content.IntentFilter;  
    import android.os.Bundle;  
    import android.support.v7.app.ActionBarActivity;  
    import android.view.View;  
    import android.widget.Button;  
      
      
    public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
      
        private Button btnSend;  
      
        private BroadCastReceive2 myReceive;  
      
        private BroadCastReceive3 myReceive3;  
      
        private IntentFilter filter;  
      
        private IntentFilter filter3;  
      
        private final static String ACTION = "com.***.mybroadcast.BroadCastReceive2";  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
      
            btnSend = (Button) findViewById(R.id.button);  
            btnSend.setOnClickListener(this);  
      
            myReceive = new BroadCastReceive2();  
            filter = new IntentFilter();  
            filter.addAction(ACTION);  
            filter.setPriority(2);//设置广播的优先级, -1000~1000 ,数字越大,优先级越高。  
      
            myReceive3 = new BroadCastReceive3();  
            filter3 = new IntentFilter();  
            filter3.addAction(ACTION);  
            filter3.setPriority(1);  
      
      
        }  
      
      
        @Override  
        protected void onResume() {  
            /** 
             * 注册广播 
             */  
            registerReceiver(myReceive, filter);  
            registerReceiver(myReceive3, filter3);  
      
      
            super.onResume();  
        }  
      
      
        @Override  
        protected void onPause() {  
            /** 
             * 注销广播 
             */  
      
            unregisterReceiver(myReceive);  
            unregisterReceiver(myReceive3);  
      
            super.onPause();  
        }  
      
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
                case R.id.button:  
                    sendBraodCast();  
                    break;  
            }  
        }  
      
        private void sendBraodCast() {  
      
            /** 
             * 申明广播的 action 行为 
             */  
            Intent intent = new Intent(ACTION);  
            intent.putExtra("key", "有序广播测试");  
      
            this.sendOrderedBroadcast(intent, null);  
        }  
      
      
        /** 
         * 内部类实现广播接收器 
         */  
        private class BroadCastReceive2 extends BroadcastReceiver {  
      
            @Override  
            public void onReceive(Context context, Intent intent) {  
                //TODO 接收到广播之后处理自己的事情  
                String action = intent.getAction();  
                String result = intent.getStringExtra("key");  
                MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
      
                Bundle bundle = new Bundle();  
                bundle.putString("key", "有序广播处理之后" + "
    " + "再次发送给下一个广播接收者");  
                intent.putExtra("bundle", bundle);  
                setResultExtras(bundle);  
                //切断广播,不再让此广播继续往下发送。  
                //  abortBroadcast();  
            }  
        }  
      
        /** 
         * 内部类实现广播接收器 
         */  
        private class BroadCastReceive3 extends BroadcastReceiver {  
      
            @Override  
            public void onReceive(Context context, Intent intent) {  
                //TODO 接收到广播之后处理自己的事情  
                String action = intent.getAction();  
                //要不要接受上一个广播接收器receiver2传来的的数据  
                Bundle bundle = getResultExtras(true);  
                MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + bundle.getString("key"));  
            }  
        }  
    }  
    

    有序广播特点:

    1.所有广播接收者的action是一致的,发送有序广播调用 sendOrderedBroadcast()方法。
    2.有序广播的接收者需要调用setPriority()方法设置广播接收者的优先级。数字越大,优先接受广播。
    3.有序广播如果需要终止 广播继续往下发送,可以调用 abortBroadcast()方法切断广播。
    4.先接收广播者可以将自己的处理结果通过setResultExtras()方法继续传递给下一个广播接收者。
    5.后接收者可以调用 getResultExtras(true)来自己决定是否接收上一个广播传递过来的数据。

    四.粘性广播:

    需要在 AndroidManifest.xml中添加权限

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

    发送广播的Activity

    package com.***.mybroadcast;  
      
    import android.content.Intent;  
    import android.os.Bundle;  
    import android.support.v7.app.ActionBarActivity;  
    import android.view.View;  
    import android.widget.Button;  
      
      
    /** 
     * 发送广播的Activity 
     */  
    public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
      
        private Button btnSend;  
      
      
        private final static String ACTION = "com.***.mybroadcast.BroadCastReceive1";  
        private final static String ACTION1 = "com.***.mybroadcast.BroadCastReceive2";  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
      
            btnSend = (Button) findViewById(R.id.button);  
            btnSend.setOnClickListener(this);  
        }  
      
      
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
                case R.id.button:  
                    sendBraodCast();  
                    break;  
            }  
        }  
      
        private void sendBraodCast() {  
      
            /** 
             * 申明广播的 action 行为 
             */  
            Intent intent = new Intent(ACTION);  
            intent.putExtra("key", "普通广播测试");  
            sendBroadcast(intent);  
      
            Intent intent1 = new Intent(ACTION1);  
            intent1.putExtra("key", "粘性广播测试");  
            sendStickyBroadcast(intent1);  
            startActivity(new Intent(this, RecevieActivity.class));  
        }  
    }  
    

    接受广播的Activity

    package com.***.mybroadcast;  
      
    import android.app.Activity;  
    import android.content.BroadcastReceiver;  
    import android.content.Context;  
    import android.content.Intent;  
    import android.content.IntentFilter;  
    import android.os.Bundle;  
      
    /** 
     * Description:接受广播的Activity 
     * User: *** 
     * Date: 2015/5/14 
     * Time: 17:03 
     */  
      
    public class RecevieActivity extends Activity {  
      
        private final static String ACTION1 = "com.***.mybroadcast.BroadCastReceive1";  
        private final static String ACTION2 = "com.***.mybroadcast.BroadCastReceive2";  
      
        private Receive receive;  
      
        private IntentFilter filter1;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
      
            receive = new Receive();  
      
            filter1 = new IntentFilter();  
            filter1.addAction(ACTION1);  
            filter1.addAction(ACTION2);  
      
        }  
      
        @Override  
        protected void onResume() {  
            super.onResume();  
            registerReceiver(receive, filter1);  
        }  
      
        @Override  
        protected void onPause() {  
            super.onPause();  
            unregisterReceiver(receive);  
        }  
      
        private class Receive extends BroadcastReceiver {  
            @Override  
            public void onReceive(Context context, Intent intent) {  
                String action = intent.getAction();  
                String result = intent.getStringExtra("key");  
                MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
            }  
        }  
    }  
    

    打印结果如下:

    从结果来看,只有粘性广播才能接收到广播信息。

    粘性广播特点:

    1.需要在AndroidManifest.xml中添加权限

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

    2.粘性广播发送除了调用方法不同sendStickyBroadcast(intent1),其他都一样。
    3.一般广播都是先注册广播,才能接收到广播,而粘性广播可以做到先发送广播,哪里需要接收该广播就哪里注册,可以后注册广播拿到广播的结果。这就是 普通广播和粘性广播的区别。从示例中也看出了普通广播在跳转到ReceiveActivity中是接受不到广播发送者发出的广播的,只有粘性广播才能接收到。

    有人会奇怪,平时也没看到哪里使用粘性广播??其实我也是看到Android 系统中 监测电池电量部分发现的。贴上代码如下:

    // Register for the battery changed event  
    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);  
      
    / Intent is sticky so using null as receiver works fine  
    // return value contains the status  
    Intent batteryStatus = this.registerReceiver(null, filter);  
      
    // Are we charging / charged?  
    int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);  
    boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING  
      || status == BatteryManager.BATTERY_STATUS_FULL;  
      
    boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;  
      
    // How are we charging?  
    int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);  
    boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;  
    boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;   
    

    广播的生命周期:

    当广播接收者接收到广播调用完onReceive()方法之后,广播的生命周期就结束了。

    因此广播接收器不能执行超过10s耗时任务,也不能在onReceive()方法中创建Thread 来执行耗时任务,你可以开启一个Service来执行后台耗时任务,具体可以参考Android 四大组件之Service 的生命周期和使用。

    广播的大概原理:

    广播是怎么发送的?又是怎么接收的?

    我们知道,只有先注册了某个广播之后,广播接收者才能收到该广播。广播注册的一个行为是将自己感兴趣的IntentFilter注册到Android系统的AMS(ActivityManagerService)中,里面保存了一个IntentFilter列表。广播发送者将自己的IntentFilter 的action行为发送到AMS中,然后遍历AMS中的IntentFilter列表,看谁订阅了该广播,然后将消息遍历发送到注册了相应IntentFilter的Activity或者Service中-----也就是会调用抽象方法onReceive()方法。其中AMS起到了中间桥梁作用。

    系统广播:

    Android系统中有很多系统广播,比如:

    Event	Description
    Intent.ACTION_BOOT_COMPLETED	Boot completed. Requires the android.permission.RECEIVE_BOOT_COMPLETEDpermission.
    Intent.ACTION_POWER_CONNECTED	Power got connected to the device.
    Intent.ACTION_POWER_DISCONNECTED	Power got disconnected to the device.
    Intent.ACTION_BATTERY_LOW	Triggered on low battery. Typically used to reduce activities in your app which consume power.
    Intent.ACTION_BATTERY_OKAY	Battery status good again.
    

    系统广播具体怎么用?网络上一搜一大把,这里就不讲了。和我们写的广播使用都差不多。

  • 相关阅读:
    Unity-JobSystem
    Unity-ECS-实践
    Unity-Editor
    网络编程-HTTPS
    网络编程-UDP、TCP
    Cast, OfType
    DataGrid
    bat 开机自动执行脚本
    bat 单行输出彩色信息
    工厂模式
  • 原文地址:https://www.cnblogs.com/zhousysu/p/5483864.html
Copyright © 2011-2022 走看看