安卓学习笔记35:广播接收者

举报
howard2005 发表于 2021/11/19 02:28:33 2021/11/19
【摘要】 文章目录 零、学习目标一、广播接收者概述(一)广播分类1、标准广播2、有序广播 (二)广播接收者作用(三)广播接收者继承关系图(四)使用广播接收者1、创建广播接收者2、注册广播接收者3、通过...

零、学习目标

  1. 知道广播接收者的作用
  2. 掌握如何创建并注册自定义广播接收者
  3. 掌握如何利用广播接收者实现组件之间的通信

一、广播接收者概述

(一)广播分类

1、标准广播

标准广播( Normal Broadcasts) 是一种完全异步执行的广播,在广播发出之后,所有的广播接收者几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。标准广播也叫无序广播,无序广播不能设置优先级,没有abortBroadcast()方法。
在这里插入图片描述

2、有序广播

有序广播( Ordered Broadcasts) 则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收者能够收到这条广播消息,当这个广播接收者中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收者是有先后顺序的,优先级高的广播接收者就可以先 收到广播消息,并且前面的广播接收者还可以截断正在传递的广播,这样后面的广播接收者就无法收到广播消息了。有序广播可以设置优先级, 有 abortBroadcast() 方法。

在这里插入图片描述

(二)广播接收者作用

  • 广播接收者可以实现组件之间的通信。安卓系统会发生一些事件的改变,比如,电量变低,收发短信,拨打电话,屏幕解锁系统会发送广播,只要应用程序接收到这条广播,就知道系统发生了什么事件,从而执行相应的代码,使用广播接受者,就可以接收广播。

(三)广播接收者继承关系图

在这里插入图片描述

(四)使用广播接收者

1、创建广播接收者

  • 新建一个类,让它继承自BroadcastReceiver,并重写父类的 onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。

2、注册广播接收者

– 动态注册广播接收者(在Java代码里)
– 静态注册广播接收者(在项目清单文件里)

3、通过意图发送广播

– 利用sendBroadcast(Intent inten)发送广播

二、案例演示 - 发送与接收广播

(一)运行效果

在这里插入图片描述
在这里插入图片描述

(二)涉及知识点

  1. 线性布局(LinearLayout)
  2. 编辑框(EditText)
  3. 按钮(Button)
  4. 广播接收者(BroadcastReceiver)

(三)实现步骤

1、创建安卓应用【SendReceiveBroadcast】

在这里插入图片描述
在这里插入图片描述

2、将背景图片拷贝到drawable目录

在这里插入图片描述

3、主布局资源文件activity_main.xml

在这里插入图片描述

<?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"
    android:background="@drawable/background"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edtMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/input_message"
        android:singleLine="true"
        android:textSize="20sp" />

    <Button
        android:id="@+id/btnSendBroadcast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doSendBroadcast"
        android:text="@string/send_broadcast"
        android:textSize="20sp" />
</LinearLayout>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

4、字符串资源文件strings.xml

在这里插入图片描述

<resources>
    <string name="app_name">发送与接收广播</string>
    <string name="input_message">请输入要广播的消息</string>
    <string name="send_broadcast">发送广播的消息</string>
</resources>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

5、创建自定义广播接收者

  • 继承BroadcastReceiver类,创建自定义广播接收者类CustomReceiver
    在这里插入图片描述
package net.hw.send_receive_broadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * 功能:自定义广播接收者
 * 作者:华卫
 * 日期:2020年12月30日
 */
public class CustomReceiver extends BroadcastReceiver {
    
    private final String TAG = "send_receive_broadcast"; // 标记
    private final String INTENT_ACTION_SEND_MESSAGE = "net.hw.intent.action.SEND_MESSAGE"; // 广播频道
    
    @Override
    public void onReceive(Context context, Intent intent) {
        // 按照频道获取广播信息
        if (intent.getAction().equals(INTENT_ACTION_SEND_MESSAGE)) {
            // 获取广播信息
            String message = intent.getStringExtra("message");
            // 输出广播信息
            Log.d(TAG, message);
        }
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

6、在项目清单文件里注册广播接收者

  • 采用静态方式注册自定义广播接收者
    在这里插入图片描述

7、主界面类 - MainActivity

在这里插入图片描述

  • 定义常量与变量
    在这里插入图片描述
  • 通过资源标识符获取控件实例
    在这里插入图片描述
  • 编写代码发送广播的信息
    在这里插入图片描述
  • 查看主界面类完整源代码
package net.hw.send_receive_broadcast;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private final String TAG = "send_receive_broadcast"; // 标记
    private final String INTENT_ACTION_SEND_MESSAGE = "net.hw.intent.action.SEND_MESSAGE"; // 广播频道
    private EditText edtMessage; // 消息编辑框
    private int broadcastCount; // 发送广播次数

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过资源标识符获取控件实例
        edtMessage = findViewById(R.id.edtMessage);
    }

    /**
     * 发送广播
     *
     * @param view
     */
    public void doSendBroadcast(View view) {
        // 统计发送广播次数
        broadcastCount++;
        // 获取用户输入要广播的信息
        String message = edtMessage.getText().toString();
        // 创建意图
        Intent intent = new Intent();
        // 设置意图动作(广播频道)
        intent.setAction(INTENT_ACTION_SEND_MESSAGE);
        // 设置意图携带的附加内容
        intent.putExtra("message", "第" + broadcastCount + "次广播信息:" + message);
        // 按照意图发送广播
        sendBroadcast(intent);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

8、启动应用,查看效果

在这里插入图片描述
在这里插入图片描述

9、采用动态方式注册广播接收者

(1)修改项目清单文件对广播接收者的注册

在这里插入图片描述

(2)在主界面类里动态注册广播接收者

在这里插入图片描述

(3)启动应用,查看效果

在这里插入图片描述

三、案例演示 - 显示播放进度

  • 本案例演示如何通过广播实现窗口与服务之间的通信

(一)运行效果

在这里插入图片描述

在这里插入图片描述

(二)涉及知识点

  1. 活动窗口(Activity)
  2. 服务(Service)
  3. 广播接收者(BroadcastReceiver)
  4. 标签(TextView)
  5. 进度条(ProgressBar)
  6. 按钮(Button)
  7. 线性布局(LinearLayout)
  8. 线程(Thread)

(三)实现步骤

1、创建安卓应用【DisplayProgress】

在这里插入图片描述
在这里插入图片描述

2、将背景图片拷贝到drwawable目录

在这里插入图片描述

3、主布局资源文件activity_main.xml

在这里插入图片描述

<?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"
    android:background="@drawable/background"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvProgress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0%"
        android:textColor="#0000ff"
        android:textSize="50sp" />

    <ProgressBar
        android:id="@+id/pbPlay"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnStart"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:onClick="doStart"
            android:text="@string/start"
            android:textSize="20sp" />

        <Button
            android:id="@+id/btnStop"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:onClick="doStop"
            android:text="@string/stop"
            android:textSize="20sp" />
    </LinearLayout>
</LinearLayout>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

4、字符串资源文件strings.xml

在这里插入图片描述

<resources>
    <string name="app_name">显示播放进度</string>
    <string name="start">开始</string>
    <string name="stop">停止</string>
</resources>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

5、创建应用程序常量接口 - AppConstants

在这里插入图片描述

package net.hw.display_progress;

/**
 * 功能:应用程序常量接口
 * 作者:华卫
 * 日期:2020年12月30日
 */
public interface AppConstants {
    String TAG = "net.hw.display_progress"; // 应用程序标记
    String INTENT_ACTION_START = "net.hw.display_progress.intent.action.START"; // 开始进度广播频道
    String INTENT_ACTION_STOP = "net.hw.display_progress.intent.action.STOP"; // 停止进度广播频道
    String INTENT_ACTION_UPDATE_PROGRESS = "net.hw.display_progress.intent.action.UPDATE_PROGRESS"; // 更新进度广播频道
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

6、创建进度服务类 - ProgressService

在这里插入图片描述

  • 继承Service类,实现AppConstants接口
    在这里插入图片描述
  • 创建内部广播接收者 - InnerBroadcastReceiver (功能代码暂时空着)
    在这里插入图片描述
  • 声明变量
    在这里插入图片描述
  • 在创建回调方法里创建并注册内部广播接收者
    在这里插入图片描述
  • 创建启动更新线程的方法 - startUpdateThread()
    在这里插入图片描述
  • 编写销毁更新线程的方法
    在这里插入图片描述
  • 在销毁回调方法里注销内部广播接收者
    在这里插入图片描述
  • 编写内部广播接收者代码
    在这里插入图片描述
  • 查看进度服务类完整源代码
package net.hw.display_progress;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

/**
 * 功能:进度服务类
 * 作者:华卫
 * 日期:2020年12月30日
 */
public class ProgressService extends Service implements AppConstants {

    private InnerBroadcastReceiver receiver; // 内部广播接收者
    private IntentFilter filter; // 意图过滤器
    private Thread thread; // 线程
    private boolean isRunning; // 线程循环控制变量
    private int progressValue; // 进度值

    /**
     * 创建回调方法
     */
    @Override
    public void onCreate() {
        super.onCreate();
        // 创建内部广播接收者
        receiver = new InnerBroadcastReceiver();
        // 创建意图过滤器
        filter = new IntentFilter();
        // 添加意图动作(广播频道)
        filter.addAction(INTENT_ACTION_START);
        filter.addAction(INTENT_ACTION_STOP);
        // 动态注册内部广播接收者
        registerReceiver(receiver, filter);
    }

    /**
     * 启动更新线程
     */
    private void startUpdateThread() {
        // 设置线程循环控制变量为真
        isRunning = true;

        // 创建更新进度值的线程
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 线程循环
                while (isRunning) {
                    // 更新进度值
                    progressValue = ++progressValue % 101;
                    // 输出调试信息
                    Log.d(TAG, "当前进度值:" + progressValue + "%");
                    // 创建意图
                    Intent intent = new Intent();
                    // 设置意图动作(广播频道)
                    intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);
                    // 设置意图携带的附加数据
                    intent.putExtra("progressValue", progressValue);
                    // 按意图发送广播
                    sendBroadcast(intent);
                    try {
                        // 让线程睡眠500毫秒
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        // 启动线程
        thread.start();
    }

    /**
     * 销毁更新线程
     */
    private void destroyUpdateThread() {
        // 设置县城循环控制变量为假
        isRunning = false;
        // 销毁更新进度的线程
        thread = null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 销毁回调方法
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        // 注销内部广播接收者
        unregisterReceiver(receiver);
    }

    /**
     * 内部广播接收者
     */
    private class InnerBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null) {
                // 根据广播频道进行不同操作
                switch (intent.getAction()) {
                    case INTENT_ACTION_START:
                        // 启动更新线程
                        startUpdateThread();
                        Log.d(TAG, "收到启动进度的广播!");
                        break;
                    case INTENT_ACTION_STOP:
                        // 销毁更新线程
                        destroyUpdateThread();
                        Log.d(TAG, "收到停止进度的广播!");
                        break;
                }
            }
        }
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136

7、在项目清单文件里注册进度服务类

在这里插入图片描述

8、主界面类 - MainActivity

在这里插入图片描述

  • 创建内部广播接收者(功能代码暂时空着)
    在这里插入图片描述

  • 声明变量
    在这里插入图片描述

  • 实现AppConstants接口
    在这里插入图片描述

  • 通过资源标识符获取控件实例
    在这里插入图片描述

  • 启动进度服务
    在这里插入图片描述

  • 创建并注册内部广播接收者
    在这里插入图片描述

  • 编写内部广播接收者代码
    在这里插入图片描述

  • 编写开始按钮单击事件处理方法
    在这里插入图片描述

  • 编写停止按钮单击事件处理方法
    在这里插入图片描述

  • 在销毁回调方法里停止服务,注销内部广播接收者
    在这里插入图片描述

  • 查看主界面类完整源代码

package net.hw.display_progress;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements AppConstants {

    private TextView tvProgress; // 显示进度值的标签
    private ProgressBar pbPlay; // 播放进度条
    private Intent intent; // 意图
    private IntentFilter filter; // 意图过滤器
    private InnerBroadcastReceiver receiver; // 内部广播接受者

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过资源标识符获取控件实例
        tvProgress = findViewById(R.id.tvProgress);
        pbPlay = findViewById(R.id.pbPlay);

        // 创建启动服务的意图
        intent = new Intent(this, ProgressService.class);
        // 启动进度服务
        startService(intent);

        // 创建内部广播接收者
        receiver = new InnerBroadcastReceiver();
        // 创建意图过滤器
        filter = new IntentFilter();
        // 添加意图动作(广播频道)
        filter.addAction(INTENT_ACTION_UPDATE_PROGRESS);
        // 动态注册内部广播接受者
        registerReceiver(receiver, filter);
    }

    /**
     * 内部广播接收者
     */
    private class InnerBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null) {
                // 收到来自进度服务所发送的广播
                if (INTENT_ACTION_UPDATE_PROGRESS.equals(intent.getAction())) {
                    // 获取广播传递过来的进度值
                    int progressValue = intent.getIntExtra("progressValue", 0);
                    // 用更新后的进度值去设置进度标签
                    tvProgress.setText(progressValue + "%");
                    // 用更新后的进度值去设置进度条
                    pbPlay.setProgress(progressValue);
                }
            }
        }
    }

    /**
     * 开始按钮单击事件处理方法
     *
     * @param view
     */
    public void doStart(View view) {
        // 创建意图
        Intent intent = new Intent();
        // 设置动作(广播频道)
        intent.setAction(INTENT_ACTION_START);
        // 按意图发送广播
        sendBroadcast(intent);
    }

    /**
     * 停止按钮单击事件处理方法
     *
     * @param view
     */
    public void doStop(View view) {
        // 创建意图
        Intent intent = new Intent();
        // 设置动作(广播频道)
        intent.setAction(INTENT_ACTION_STOP);
        // 按意图发送广播
        sendBroadcast(intent);
    }

    /**
     * 销毁回调方法
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止服务
        stopService(intent);
        // 注销广播接收者
        unregisterReceiver(receiver);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

9、启动应用,查看效果

在这里插入图片描述
在这里插入图片描述

文章来源: howard2005.blog.csdn.net,作者:howard2005,版权归原作者所有,如需转载,请联系作者。

原文链接:howard2005.blog.csdn.net/article/details/111941533

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。