广播介绍


1.安卓四大组件之一 2.广播使用了观察者模式 3.进程间通信


广播发送

  • 广播分类

1.普通广播(Broadcast) <1>.发送一个广播,所有监听该广播的广播接收者都可以监听到改广播 <2>.完全异步的,接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播 2.有序广播(OrderedBroadcast) <1>.按照接收者的优先级顺序接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大,优先级越高 <2>.可以终止广播意图的继续传播.接收者可以篡改内容.广播Intent的传播一旦终止,后面的接收者就无法接收到广播 3.粘性广播(StickyBroadcast) <1>.粘性广播在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态 <2>.粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据 <3>.发送黏性广播需要权限<uses-permission android:name="android.permission.BROADCAST_STICKY" /> <4>.粘性广播一般用来确保重要的状态改变后的信息被持久保存,并且能随时广播给新的广播接收器 <5>.可以【先发送,后接收】


android中粘性广播如何移除 android 粘性广播_动态注册


  • 发送广播
public class MainActivity extends Activity {
    private static final String NORMAL_ACTION = "com.example.broadcast_NORMAL";
    private static final String ORDER_ACTION = "com.example.broadcast_ORDER";
    private static final String STICKY_ACTION = "com.example.broadcast_STICKY";

    private static final String RECEIVER_PERMISSION = "com.example.broadcast_RECEIVER_PERMISSION";

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

        sendNormalBroadcast();
        sendOrderBroadcast();
        sendStickyBroadcast();
    }

    // 发送普通广播
    private void sendNormalBroadcast() {
        Intent intent = new Intent();
        intent.setAction(NORMAL_ACTION);
        intent.putExtra("args", "Normal Broadcast");
        sendBroadcast(intent);
    }

    // 发送有序广播
    private void sendOrderBroadcast() {
        Intent intent = new Intent();
        intent.setAction(ORDER_ACTION);
        intent.putExtra("args", "Order Broadcast");
        sendOrderedBroadcast(intent, RECEIVER_PERMISSION);
    }

    // 发送粘性广播
    private void sendStickyBroadcast() {
        Intent intent = new Intent();
        intent.setAction(STICKY_ACTION);
        intent.putExtra("args", "Sticky Broadcast");
        sendStickyBroadcast(intent);
    }
}


广播注册

  • 注册广播方式

1.静态注册 在AndroidManifest.xml文件中定义,注册的广播接收器必须继承BroadReceiver 2.动态注册 在程序中使用Context.registerReceiver进行注册


  • 静态注册方式
<!-- 配置到AndroidManifest.xml中 -->
<receiver android:name=".BootBroadcastReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>


// 继承BroadcastReceiver,重写onReceive方法
public class BootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO something
    }
}


  • 动态注册方式
public class TestActivity extends Activity {
    private IncomingSMSReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReceiver = new IncomingSMSReceiver();
        registerReceiver();
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver();
        super.onDestroy();
    }

    // 注册IncomingSMSReceiver广播接收器
    private void registerReceiver() {
        IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
        registerReceiver(mReceiver, filter);
    }

    // 程序退出后,需要取消注册
    private void unregisterReceiver() {
        unregisterReceiver(mReceiver);
    }

    // 继承BroadcastReceiver,重写onReceive方法
    private class IncomingSMSReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO
        }
    }
}


  • 动态注册与静态注册区别

1.动态注册的广播永远要快于静态注册的广播,不管静态注册的优先级设置的多高,不管动态注册的优先级有多低 2.动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意:在activity结束前,移除广播接收器 静态注册是常驻型 ,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行 3.在同一个优先级下,谁先启动的快,谁将先接收到广播


广播接收

  • 接收广播

通过静态或动态方式注册后,重写onReceive方法,当收到广播后会回调该方法


  • 常见系统广播
// 开机启动完成
Intent.ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";

// 外置存储卸载/挂载
Intent.ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
Intent.ACTION_MEDIA_MOUNTED = "android.intent.action.MEDIA_MOUNTED";

// 灭屏/亮屏
Intent.ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"
Intent.ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";

// 飞行模式状态改变
Intent.ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";

// 低电
Intent.ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";

// 配置改变,如屏幕旋转
Intent.ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";

// 插入耳机
Intent.ACTION_HEADSET_PLUG = android.media.AudioManager.ACTION_HEADSET_PLUG;

// 关机
Intent.ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";

// 重启
Intent.ACTION_REBOOT = "android.intent.action.REBOOT";


  • 实例
public class ReceiveBroadcast extends Activity {
    private static final String TAG = "ReceiveBroadcast";

    private static final String NORMAL_ACTION = "com.example.broadcast_NORMAL";
    private static final String ORDER_ACTION = "com.example.broadcast_ORDER";
    private static final String STICKY_ACTION = "com.example.broadcast_STICKY";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        IntentFilter filter = new IntentFilter();
        filter.addAction(NORMAL_ACTION);
        filter.addAction(ORDER_ACTION);
        filter.addAction(STICKY_ACTION);
        registerReceiver(mBroadcastReceiver, filter);
    }

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (NORMAL_ACTION.equals(action)) {
                // 接收无序广播
                String message = intent.getStringExtra("args");
                Log.v(TAG, "无序广播:" + message);
            } else if (ORDER_ACTION.equals(action)) {
                // 接收有序广播
                Bundle bundle = intent.getExtras();
                bundle.putBoolean("is_continue", true);

                // 向后面的接收者传递数据
                setResultExtras(bundle);

                // 终止继续传递
                // abortBroadcast();
            } else if (STICKY_ACTION.equals(action)) {
                // 接收粘性广播,先发送,后注册也能收到
                String message = intent.getStringExtra("args");
                Log.v(TAG, "粘性广播:" + message);

                // 移除该粘性广播
                removeStickyBroadcast(intent);
            }
        }
    };
}


实现原理

  • 原理

1. 广播使用了观察者模式实现 2. 接收广播前需要注册,主要注册到ActivityManagerService中,一个广播发出后会到AMS中,这时候AMS会对注册了该广播的程序进行派发


  • 原理图

android中粘性广播如何移除 android 粘性广播_ide_02


流程

  • 注册流程

动态注册 - 动态注册是直接注册到AMS中

android中粘性广播如何移除 android 粘性广播_动态注册_03

android中粘性广播如何移除 android 粘性广播_android中粘性广播如何移除_04

android中粘性广播如何移除 android 粘性广播_android中粘性广播如何移除_05


静态注册 - 静态注册是配置到配置清单文件里,由PMS解析,AMS直接从PMS获取

android中粘性广播如何移除 android 粘性广播_ide_06

android中粘性广播如何移除 android 粘性广播_ide_07


  • 发送接收流程

派发流程

android中粘性广播如何移除 android 粘性广播_动态注册_08


无序广播派发与接收流程

android中粘性广播如何移除 android 粘性广播_动态注册_09