Android 应用开发 收发应用广播

目录

1.收发标准广播

(1)发送广播

(2)定义广播接收器

(3)开关广播接收器

2.收发有序广播

(1)一个广播存在多个接收器,这些接收器需要排队收听广播,这意味着该广播是条有序广播。

2.定义有序广播接收器

3.注册有序广播的多个接收器

3.收发静态广播

4.定时管理器 AlarmManager

常见方法说明:

1.定义定时器的广播接收器

2.开关定时器的广播接收器

3.设置定时器的播放规则


1.收发标准广播

(1)发送广播

只需要创建意图再调用sendBroadcast方法发送广播即可。

public class BroadStandardActivity extends AppCompatActivity implements View.OnClickListener {

// 这是广播的动作名称,发送广播和接收广播都以它作为接头暗号
    private final static String STANDARD_ACTION = "com.example.chapter04.standard";
    private TextView tv_standard; // 声明一个文本视图对象


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broad_standard);
        tv_standard = findViewById(R.id.tv_standard);
        tv_standard.setText(mDesc);
        findViewById(R.id.btn_send_standard).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_send_standard) {
            Intent intent = new Intent(STANDARD_ACTION); // 创建指定动作的意图
            sendBroadcast(intent); // 发送标准广播
        }
    }
}

(2)定义广播接收器

接收器主要规定两个事情,一个是接收什么样的广播,另一个接收广播后要做什么。Android提供了抽象之后的接收器基类BroadcastReceiver,开发者自定义的接收器都从BroadcastReceiver派生而来,新定义的接收器需要重写onReceive方法,方法内部先判断当前广播是否符合待接收广播名称,校验通过后在开展后续业务逻辑。

    private String mDesc = "这里查看标准广播的收听信息";

    // 定义一个标准广播的接收器
    private class StandardReceiver extends BroadcastReceiver {
        // 一旦接收到标准广播,马上触发接收器的onReceive方法
        @Override
        public void onReceive(Context context, Intent intent) {
            // 广播意图非空,且接头暗号正确
            if (intent != null && intent.getAction().equals(STANDARD_ACTION)) {
                mDesc = String.format("%s\n%s 收到一个标准广播", mDesc, DateUtil.getNowTime());
                tv_standard.setText(mDesc);
            }
        }

(3)开关广播接收器

    private StandardReceiver standardReceiver; // 声明一个标准广播的接收器实例
    @Override
    protected void onStart() {
        super.onStart();
        standardReceiver = new StandardReceiver(); // 创建一个标准广播的接收器
        // 创建一个意图过滤器,只处理STANDARD_ACTION的广播
        IntentFilter filter = new IntentFilter(STANDARD_ACTION);
        registerReceiver(standardReceiver, filter); // 注册接收器,注册之后才能正常接收广播
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(standardReceiver); // 注销接收器,注销之后就不再接收广播
    }

2.收发有序广播

(1)一个广播存在多个接收器,这些接收器需要排队收听广播,这意味着该广播是条有序广播。

(2)先收到广播的接收器A,既可以让其他接收器继续收听广播,也可以中断广播不让其它接收器收听。

有序广播的收发有以下几个步骤:

1.发送广播时注明是有序广播

之前发送标准广播用到了sendBroadcast方法,可是该方法发出来的广播是无序的,只有调用sendOrderedBroadcast才能发送有序广播,发送代码示例如下:

Intent intent = new Intent(ORDER_ACTION); // 创建一个指定动作的意图
sendOrderedBroadcast(intent, null); // 发送有序广播

2.定义有序广播接收器

接收器的定义代码基本不变,也要从BroadcastReceiver继承而来,唯一的区别是有序广播的接收器允许中断广播。倘若在接收器内部调用abortBroadcast方法,就会中断有序广播,使得后面的接收器不能再接收广播。

    private OrderAReceiver orderAReceiver; // 声明有序广播接收器A的实例

    // 定义一个有序广播的接收器A
    private class OrderAReceiver extends BroadcastReceiver {
        // 一旦接收到有序广播,马上触发接收器的onReceive方法
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null && intent.getAction().equals(ORDER_ACTION)) {
                String desc = String.format("%s%s 接收器A收到一个有序广播\n",
                        tv_order.getText().toString(), DateUtil.getNowTime());
                tv_order.setText(desc);
                if (ck_abort.isChecked()) {
                    abortBroadcast(); // 中断广播,此时后面的接收器无法收到该广播
                }
            }
        }
    }

3.注册有序广播的多个接收器

接收器的注册操作同样调用registerReceiver方法,为了给接收器排队,还需调用意图过滤器的setPriority方法设置优先级,优先级越大的接收器,越先收到有序广播。如果不设置优先级,或者两个接收器优先级相等,那么越早注册的接收器,会越先收到有序广播。

        // 多个接收器处理有序广播的顺序规则为:
        // 1、优先级越大的接收器,越早收到有序广播;
        // 2、优先级相同的时候,越早注册的接收器越早收到有序广播
        orderAReceiver = new OrderAReceiver(); // 创建一个有序广播的接收器A
        // 创建一个意图过滤器A,只处理ORDER_ACTION的广播
        IntentFilter filterA = new IntentFilter(ORDER_ACTION);
        filterA.setPriority(8); // 设置过滤器A的优先级,数值越大优先级越高
        registerReceiver(orderAReceiver, filterA); // 注册接收器A,注册之后才能正常接收广播

3.收发静态广播

在AndroidManifest.xml中注册接收器,该方法被称作静态注册,在代码中注册接收器,该方式被成为动态注册。创建一个类来做广播接收处理,同时在AndroidManifest.xml中添加以下代码


public class ShockReceiver extends BroadcastReceiver {
    private static final String TAG = "ShockReceiver";
    // 静态注册时候的action、发送广播时的action、接收广播时的action,三者需要保持一致
    public static final String SHOCK_ACTION = "com.example.chapter04.shock";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive");
        if (intent.getAction().equals(ShockReceiver.SHOCK_ACTION)){
            // 从系统服务中获取震动管理器
            Vibrator vb = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
            vb.vibrate(500); // 命令震动器吱吱个若干秒,这里的500表示500毫秒
        }
    }

}
        <receiver
            android:name=".receiver.ShockReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.chapter04.shock" />
            </intent-filter>
        </receiver>

发送广播

            // Android8.0之后删除了大部分静态注册,防止退出App后仍在接收广播,
            // 为了让应用能够继续接收静态广播,需要给静态注册的广播指定包名。
            String receiverPath = "com.example.chapter04.receiver.ShockReceiver";
            Intent intent = new Intent(ShockReceiver.SHOCK_ACTION); // 创建一个指定动作的意图
            // 发送静态广播之时,需要通过setComponent方法指定接收器的完整路径
            ComponentName componentName  = new ComponentName(this, receiverPath);
            intent.setComponent(componentName); // 设置意图的组件信息
            sendBroadcast(intent); // 发送静态广播
            Toast.makeText(this, "已发送震动广播", Toast.LENGTH_SHORT).show();

4.定时管理器 AlarmManager

        // 从系统服务中获取闹钟管理器
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);

常见方法说明:

set:设置一次性定时器,第一个参数为定时器类型,通常填alarmMgr .RTC_WAKEUP;第二个参数为期望的执行时刻(单位为毫秒),第三个参数为待执行的延迟意图(PendingIntent类型)

setAndAllowWhiteIdle:设置一次性定时器,参数说明同set方法,不同之处在于:即使设备处于空闲状态,也会保证执行定时器。因为从Android 6.0中,set方法在暗屏不保证发送广播,必须调用setAndAllowWhileIdle方法才能保证发送广播。

setRepeating:设置重复定时器,第一个参数为定时器类型;第二个参数为首次执行时间,第三个参数为下次执行的间隔时间,第四个参数为待执行的延迟意图,然而setRepeating方法不保证按时发送广播,只能通过setAndAllowWhiteIdle方法间接实现重复定时功能。

cancel:取消指定延时意图的定时器

PendingIntent和Intent区别:

(1)PendingIntent代表延迟的意图,它指向的组件不会马上被激活;而Intent代表实时的意图,一旦被启动,它指向的组件会被马上激活。

(2)PendingIntent是一类消息的组合,不但包含目标的Intent对象,还包含请求代码,请求方式等信息。

(3)PendingIntent对象在创建时便已知晓将要用于活动还是广播,例如调用getActivity方法得到的是活动跳转的延迟意图,调用getBroadcast方法得到的是广播发送的延迟意图。

1.定义定时器的广播接收器

闹钟广播的接收器采用动态注册方式,它的实现途径与标准广播类似,都要从BroadcastReceiver派生新的接收器,并重写onReceive方法

    // 声明一个闹钟广播事件的标识串
    private String ALARM_ACTION = "com.example.chapter04.alarm";
    private String mDesc = ""; // 闹钟时间到达的描述


    // 定义一个闹钟广播的接收器
    public class AlarmReceiver extends BroadcastReceiver {
        // 一旦接收到闹钟时间到达的广播,马上触发接收器的onReceive方法
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null) {
                mDesc = String.format("%s\n%s 闹钟时间到达", mDesc, DateUtil.getNowTime());
                tv_alarm.setText(mDesc);
                // 从系统服务中获取震动管理器
                Vibrator vb = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
                vb.vibrate(500); // 命令震动器吱吱个若干秒
                if (ck_repeate.isChecked()) { // 需要重复闹钟广播
                    sendAlarm(); // 发送闹钟广播
                }
            }
        }
    }

2.开关定时器的广播接收器

    private AlarmReceiver alarmReceiver; // 声明一个闹钟的广播接收器
    @Override
    public void onStart() {
        super.onStart();
        alarmReceiver = new AlarmReceiver(); // 创建一个闹钟的广播接收器
        // 创建一个意图过滤器,只处理指定事件来源的广播
        IntentFilter filter = new IntentFilter(ALARM_ACTION);
        registerReceiver(alarmReceiver, filter); // 注册接收器,注册之后才能正常接收广播
    }

    @Override
    public void onStop() {
        super.onStop();
        unregisterReceiver(alarmReceiver); // 注销接收器,注销之后就不再接收广播
    }

3.设置定时器的播放规则

    // 发送闹钟广播
    private void sendAlarm() {
        Intent intent = new Intent(ALARM_ACTION); // 创建一个广播事件的意图
        // 从Android12开始,必须添加 FLAG_IMMUTABLE 或者 FLAG_MUTABLE
        // 创建一个用于广播的延迟意图
        PendingIntent pIntent = PendingIntent.getBroadcast(this, 0,
                intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        // 从系统服务中获取闹钟管理器
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        long delayTime = System.currentTimeMillis() + mDelay*1000; // 给当前时间加上若干秒
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 允许在空闲时发送广播,Android6.0之后新增的方法
            alarmMgr.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, delayTime, pIntent);
        } else {
            // 设置一次性闹钟,延迟若干秒后,携带延迟意图发送闹钟广播(但Android6.0之后,set方法在暗屏时不保证发送广播,必须调用setAndAllowWhileIdle方法)
            alarmMgr.set(AlarmManager.RTC_WAKEUP, delayTime, pIntent);
        }
//        // 设置重复闹钟,每隔一定间隔就发送闹钟广播(但从Android4.4开始,setRepeating方法不保证按时发送广播)
//        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
//                mDelay*1000, pIntent);
    }
  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值