Android 蓝牙配对Settings应用里面的简要流程记录

news2024/11/25 20:32:33

Android 蓝牙配对Settings应用里面的简要流程记录

文章目录

  • Android 蓝牙配对Settings应用里面的简要流程记录
    • 一、前言
    • 二、Settings蓝牙配对的关键代码
      • 1、接收蓝牙请求的地方 AndroidManifest.xml
      • 2、BluetoothPairingRequest
      • 3、BluetoothPairingService
      • 4、BluetoothPairingDialog
      • 5、BluetoothNameDialogFragment.java
      • 6、BluetoothPairingController
    • 三、其他
      • 1、Settings和TvSettings的配对界面
        • (1)TvSettings蓝牙配对对话框
        • (2)Settings蓝牙配对对话框
      • 2、自定义的应用界面监听和处理蓝牙配对广播
      • 3、Android 蓝牙相关广播介绍
      • 4、Android13 不能静态注册的几个广播
      • 5、Android13 蓝牙协议属性配置详解

一、前言

本文只是简单分析一下原生设置Settings中蓝牙配对的大致流程,具体细节有需要的自行研究。

另外我这里的开发平台是AML平台的,所以会有Settings和TvSettings,
其实这两个应用都会监听到蓝牙配请求,都会进行处理,这也是为啥会出现两次蓝牙配对弹框确认的情况。

如果想看看蓝牙配对流程或者蓝牙配对界面就行修改可以收藏看看。

二、Settings蓝牙配对的关键代码

Settings中蓝牙界面和蓝牙相关逻辑的代码,都是在:packages\apps\Settings\src\com\android\settings\bluetooth\ 目录

1、接收蓝牙请求的地方 AndroidManifest.xml

packages\apps\Settings\src\com\android\Settings\AndroidManifest.xml

<activity android:name=".bluetooth.BluetoothPairingDialog" //(1)这是一个Activity
    android:permission="android.permission.BLUETOOTH_PRIVILEGED"
    android:excludeFromRecents="true"
    android:windowSoftInputMode="stateVisible|adjustResize"
    android:theme="@style/Theme.AlertDialog"
    android:exported="true"
    android:taskAffinity=".bluetooth.BluetoothPairingDialog">
    <intent-filter android:priority="1">
    	//(2)接收蓝牙请求
   	 	<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
    	<category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
        
<receiver android:name=".bluetooth.BluetoothPairingRequest" //(3)这是一个静态广播接收者
        android:exported="true">
	<intent-filter>
		//(4)接收蓝牙请求
        <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
        <action android:name="android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE"/>
	</intent-filter>
</receiver>

2、BluetoothPairingRequest

Settings\src\com\android\settings\bluetooth\BluetoothPairingRequest .java

public final class BluetoothPairingRequest extends BroadcastReceiver {
    private static final String TAG = "BluetoothPairingRequest";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action == null) {
            return;
        }
。。。
            if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT
                ...) {
                device.setPairingConfirmation(true); //(1)直接确认配对的情况
            } else if (powerManager.isInteractive() && shouldShowDialog) {
                // Since the screen is on and the BT-related activity is in the foreground,
                // just open the dialog
                // convert broadcast intent into activity intent (same action string)
                Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(
                    context, intent, BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND);
				//(2)拉起蓝牙配对对话框
                context.startActivityAsUser(pairingIntent, UserHandle.CURRENT);
            } else {
                // (3)拉起 BluetoothPairingService
                intent.setClass(context, BluetoothPairingService.class);
                intent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
                context.startServiceAsUser(intent, UserHandle.CURRENT);
    ...
		
            mBluetoothManager.getCachedDeviceManager().pairDeviceByCsip(device, groupId);
        }
    }
}

可以看到这个静态的广播接收者,主要功能大概有:

某些条件下直接确认配对设备

某些条件下拉起蓝牙配对确认对话框

某些条件下拉起蓝牙配对服务

AndroidManifest.xml 已经监听配对会拉起蓝牙配对对话框,这里再拉起会冲突吗?

其实不会,因为这里会有判断对话框是否已经拉起。

3、BluetoothPairingService

Settings\src\com\android\settings\bluetooth\BluetoothPairingService.java

//取消配对
mDevice.cancelBondProcess();

这个主要是启动蓝牙服务;

BluetoothPairingService主要是监听配对是否取消和配对过程异常等情况,具体逻辑就不分析了。

4、BluetoothPairingDialog

Settings\src\com\android\settings\bluetooth\BluetoothPairingDialog.java

这里主要是拉起显示配对的对话框和随时监听配对情况

public class BluetoothPairingDialog extends FragmentActivity {


    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //如果已经绑定了 或者取消配对都会关闭对话框界面
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                        BluetoothDevice.ERROR);
                if (bondState == BluetoothDevice.BOND_BONDED ||
                        bondState == BluetoothDevice.BOND_NONE) {
                    dismiss();
                }
            } else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (device == null || mBluetoothPairingController.deviceEquals(device)) {
                    dismiss();
                }
            }
        }
    };

  @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BluetoothPairingDialogFragment bluetoothFragment = ...;
        //正常情况下会拉起蓝牙配对对话框
        if (!fragmentFound) {
            bluetoothFragment.show(getSupportFragmentManager(), FRAGMENT_TAG);
        }
    }


}

从上面代码看,BluetoothPairingDialog主要作用是拉起对话框界面BluetoothPairingDialogFragment;

如果要修改蓝牙对话对话框的界面和相关信息,不是修改 BluetoothPairingDialog 的代码,

而是要修改BluetoothNameDialogFragment 的代码。

5、BluetoothNameDialogFragment.java

packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothNameDialogFragment.java

该界面主要是根据情况显示配对对话框的内容

public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment {

	//里面的代码基本都是对话框界面和相关逻辑的控制
...

	//点击取消和确认配对情况的回调
    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            mPositiveClicked = true;
            mPairingController.onDialogPositiveClick(this);
        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
            mPairingController.onDialogNegativeClick(this);
        }
        mPairingDialogActivity.dismiss();
    }

}

6、BluetoothPairingController

Settings\src\com\android\settings\bluetooth\BluetoothPairingController.java

这个类就相当于一个工具类,执行具体的逻辑。

public class BluetoothPairingController implements OnCheckedChangeListener,
        BluetoothPairingDialogListener {
	//确认配对后的操作
    private void onPair(String passkey) {
        Log.d(TAG, "Pairing dialog accepted");
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN:
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
                mDevice.setPin(passkey);
                break;


            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
                mDevice.setPairingConfirmation(true); //确认配对关键
                break;

            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                // Do nothing.
                break;

            default:
                Log.e(TAG, "Incorrect pairing type received");
        }
    }

	//取消配对或者关闭配对对话框的操作
    public void onCancel() {
            Log.d(TAG, "Pairing dialog canceled");
            mDevice.cancelBondProcess(); //取消配对关键
    }
}

三、其他

1、Settings和TvSettings的配对界面

dumpsys window 查看相关界面信息:

//(1)查看Settings 的配对界面显示情况
console:/ # dumpsys window| grep mFoc
  mFocusedApp=ActivityRecord{e4d15f7 u0 com.android.settings/.bluetooth.BluetoothPairingDialog t30}
    mFocusedWindow=Window{5509839 u0 com.android.settings/com.android.settings.bluetooth.BluetoothPairingDialog}
console:/ # 
console:/ #

//(2)查看TvSettings 的配对界面显示情况
console:/ # dumpsys window| grep mFoc
  mFocusedApp=ActivityRecord{f08fb5d u0 com.android.tv.settings/.accessories.BluetoothPairingDialog t31}
    mFocusedWindow=Window{931897e u0 com.android.tv.settings/com.android.tv.settings.accessories.BluetoothPairingDialog}

console:/ #

从dumpsys window 的窗口信息可以看到:

1、Settings的应用包名是:com.android.settings
2、TvSettings的应用包名是:com.android.tv.settings
3、Settings拉起配对对话框的类是:com.android.settings.bluetooth.BluetoothPairingDialog
4、TvSettings拉起配对对话框的类是:com.android.tv.settings.accessories.BluetoothPairingDialog

Settings和TvSettings的代码都在packages/apps/目录下,

原生Settings的具体逻辑是比TvSettings处理更详细一些,有兴趣的可以自己看看。

2、TvSettings蓝牙配对对话框和原生Settings配对对话框

(1)TvSettings蓝牙配对对话框

在这里插入图片描述

(2)Settings蓝牙配对对话框

在这里插入图片描述

(3)隐藏"通讯录访问"选框

有些方案是商显或者平板方案,可能需要取消这个现实,修改的地方;

Settings\src\com\android\settings\bluetooth\BluetoothPairingDialogFragment.java

//	contactSharing.setVisibility(mPairingController.isContactSharingVisible() ? View.VISIBLE : View.GONE);
        //隐藏"访问通讯录和通话记录"选项
        contactSharing.setVisibility(View.GONE);

可能有多种对话框会显示,全局搜索 “contactSharing.setVisibility”进行修改就可以了。

修改后的样式:

在这里插入图片描述

隐藏"通讯录选项"还可以修改:BluetoothPairingController的isContactSharingVisible()方法逻辑。

3、如果要去除TvSettings 的蓝牙配对监听

package\apps\TvSettings\Settings\AndroidManifest.xml

删除或者注释掉下面这段代码就OK了:

        <receiver
            android:name=".accessories.BluetoothPairingRequest"
            android:exported="true">
            <intent-filter>
                <action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/>
            </intent-filter>
        </receiver>

        <activity
            android:name=".accessories.BluetoothPairingDialog"
            android:configChanges="keyboard|keyboardHidden|navigation"
            android:excludeFromRecents="true"
            android:exported="true"
            android:permission="android.permission.BLUETOOTH_PRIVILEGED"
            android:taskAffinity="">
            <intent-filter>
                <action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

2、自定义的应用界面监听和处理蓝牙配对广播

主要代码如下:

//监听蓝牙配对广播
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST); //;蓝牙配对广播
context.registerReceiver(mBluetoothReceiver, mIntentFilter);

class BluetoothReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context content, Intent intent) {
            String action = intent.getAction();
            LogUtil.debug("onReceive action = " + action);
            if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {

BluetoothDevice device =  intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//设置蓝牙配对
                device.setPairingConfirmation(true);
                abortBroadcast();//关闭广播传递,防止原生设置监听到配对
            }
  }      

这里是监听到蓝牙配对后,后台直接确认配对,不用点击系统Settings的配对对话框就会确认配对。

并且这里进行了 abortBroadcast ,其他应用就不会收到蓝牙配对广播。

动态监听的方式肯定是比静态静态的方式更快收到广播。

自定义代码中也可以自己写对话框确认是否配对和取消配对。

3、Android 蓝牙相关广播介绍

蓝牙相关广播都是在 BluetoothDevice.java 和 BluetoothAdapter.java 中进行了定义。

蓝牙相关广播主要包括:蓝牙开关,蓝牙连接,蓝牙状态改变,蓝牙配对等等等等。

//Android13 中的源码地址:

packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothDevice.java

packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothAdapter.java

https://blog.csdn.net/wenzhi20102321/article/details/134956116

4、Android13 不能静态注册的几个广播

android.intent.action.SCREEN_ON //屏幕亮起

android.intent.action.SCREEN_OFF//屏幕亮起

android.intent.action.BATTERY_CHANGED //电池电量改变

android.intent.action.CONFIGURATION_CHANGED //配置改变,界面语言,设备方向等配置信息

android.intent.action.TIME_TICK //每分钟回调一次

具体内容:

https://blog.csdn.net/wenzhi20102321/article/details/134956090

5、Android13 蓝牙协议属性配置详解

https://blog.csdn.net/wenzhi20102321/article/details/139703045

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1827542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

石头、剪子、布小游戏图形化

石头、剪子、布小游戏图形化 也是之前编写了一个石头、剪子、布的小游戏&#xff0c;总感觉界面不够友好&#xff0c;AI时代到来&#xff0c;一切都无所不能&#xff0c;而且编程效率大大提高了。所以用AI大模型进行程序代码重构&#xff0c;再稍加修改&#xff0c;效果还不错…

LLM proj - 审稿大模型

常用数据处理 主要是四种方式&#xff1a;正则表达式、AC自动机、困惑度过滤低质文本、最小哈希算法实现文本去重 1. 正则表达式&#xff0c;去做一些模式匹配 ex&#xff1a; # 论文的评审内容有时会存在大量列举reference&#xff08;参考文献&#xff09;的情况 # 这些r…

KKT基础知识

KKT条件定义 KKT条件(Karush–Kuhn–Tucker conditions)是最优化&#xff08;特别是非线性规划&#xff09;领域最重要的成果之一&#xff0c;是判断某点是极值点的必要条件。 最优化问题 要选择一组参数&#xff08;变量&#xff09;&#xff0c;在满足一定的限制条件&…

Unity动态添加聊天文本

1.创建一个滚动视图 2.调整滚动视图的位置并删掉这个 3.创建一个输入框和一个按钮 这里插一句一定要给content添加这个组件并设置单元格大小 4创建一个脚本并编写下面代码 using System.Collections; using System.Collections.Generic; using TMPro; using Unity.VisualScrip…

⭐Unity 控制任意UI的渐隐渐显

使用脚本之前先给要控制的UI加上CanvasGroup组件 解释: 这个脚本使用协程来逐渐改变CanvasGroup的alpha值&#xff0c;从而实现渐隐和渐显的效果。 Mathf.Lerp函数用于在指定的时间内平滑地从当前透明度过渡到目标透明度。 通过调用FadeIn和FadeOut方法&#xff0c;你可以在任…

人工智能在风险管理中的创新之路及案例分析

随着科技的日新月异&#xff0c;人工智能&#xff08;AI&#xff09;技术已广泛应用于各个领域&#xff0c;特别是在风险管理方面&#xff0c;其展现出的巨大潜力和实际应用价值引人瞩目。本文将结合具体案例&#xff0c;深入探讨AI在风险管理中的创新应用及其带来的行业变革。…

FANUC机器人SRVO-454和SRVO-455故障报警处理总结

FANUC机器人SRVO-454和SRVO-455故障报警处理总结 公司内的一台FANUC机器人(型号:M-900iB;控制柜型号:R-30iB)正常运转过程中突然报警: SRVO-455 CPU看门狗(G:1 A:2),按Reset键无法消除该报警; 查看SRVO-455故障报警的具体内容,如下图所示: 由于现场没有备用的伺服放…

ubuntu 22.04下利用webmin 搭建一个Wordpress 网站(2)

上次我们讲到第二部分&#xff0c;今天我们继续这一个话题 第三部分&#xff1a;利用webmin创建一个wordpress网站 1、在 Webmin 内安裝Apache 未使用的模块> Apache Webserver > 现在安装 会出现如下图所示的有关软件 刷新模快后 检查开机时要自动启动Apache 测…

Midjourney提示词终极指南(完整版)

在这篇博客中&#xff0c;我们深入研究了使用提示的艺术&#xff0c;以利用Midjourney的AI功能的力量。我们将探索各种技术&#xff0c;以创建个性化和迷人的图像&#xff0c;将你的创意想法转变为令人惊叹的视觉杰作。 1. 了解提示词 提示是简短的文字描述或关键词&#xff…

JavaScript——初识:JavaScript的组成、输入和输出语句... | JavaScript基础:变量,数据类型转换

目录 初识JavaScript JavaScript的组成 输入和输出语句 ECMAScript 6保留关键字 变量的命名规范 注意事项 JavaScript基础 变量的数据类型 数据类型分类 数据类型转换 转换为字符串型 转换为数字型 转换为布尔型 例题 初识JavaScript JavaScript的组成 Java…

SpringAI快速上手

一、导入依赖 镜像&#xff08;导入maven依赖&#xff09; <repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>…

RPG游戏完整指南

环境&#xff1a;unity2021urp 本教程教大家如何使用Unity创建一个RPG游戏&#xff0c;玩家可以在城镇场景中进行导航并寻找战斗&#xff0c;并在战斗中遇到不同类型的敌人。玩家可以向敌人施加不同的动作&#xff0c;如&#xff1a;常规攻击和撤离。这会是一个十分有趣的体验。…

大疆Pocket2手持记录仪格式化恢复方法

大疆Pocket系列是手持类产品&#xff0c;此类产品处理过不少&#xff0c;今天来看一个Pocket2误格式化之后的恢复方法。 故障存储:256G存储卡 /文件系统&#xff1a;exFAT 故障现象: 客户描述其经常对存储进行格式化&#xff0c;一般重新拍就会格式化一次&#xff0c;需要恢…

Linux下的串口通信

串口通信 基础知识&#xff1a; 什么是串口&#xff1f; 串口全称串行通信接口&#xff0c;是一种常用于电子设备之间通信的异步&#xff0c;全双工接口&#xff0c;典型的串口通信只需要 3 根线&#xff0c;分别是地线 (GND)&#xff0c;发送线(TX)&#xff0c;接收线(RX)。如…

Excel/WPS《超级处理器》功能介绍与安装下载

超级处理器是基于Excel或WPS开发的一款插件&#xff0c;拥有近300个功能&#xff0c;非常简单高效的处理表格数据&#xff0c;安装即可使用。 点击此处&#xff1a;超i处理器安装下载 Excel菜单&#xff0c;显示如下图所示&#xff1a; WPS菜单显示&#xff0c;如下图所示&am…

运算符与表达式

运算符和表达式是C语言编程的基础构建块&#xff0c;它们共同构成了C语言程序的核心逻辑和计算。理解和掌握运算符和表达式的相关知识&#xff0c;对于编写高效、易读的C语言代码至关重要。 一、运算符概述 运算符是C语言中用于执行各种操作的符号&#xff0c;它们可以对变量、…

【odoo】右上角的提示(通知服务)

概要 在Odoo中&#xff0c;右上角的提示&#xff08;通知服务&#xff09;用于显示系统消息、警告、错误或信息提示。这个功能通过 JavaScript 在前端实现&#xff0c;并且使用 Odoo Web 框架提供的现成功能。 提示类型 信息提示 (Info)&#xff1a;用于显示普通信息。这类提示…

Windows配置域名映射IP

一、找到 hosts 文件 打开 C:\Windows\System32\drivers\etc 二、添加hosts文件修改、写入权限 右击hosts文件&#xff0c;点击属性 -> 安全 -> Users -> 编辑 -> Users -> 添加修改、写入权限 -> 确定 -> 确定 三、添加映射规则 在文件尾部添加一行映射…

企业数据中台功能介绍

参考视频&#xff1a; 企业级数据中台功能演示_哔哩哔哩_bilibili 具体项目&#xff1a; 平台基础设施: 系统管理,系统监控&#xff08;登录/操作日志&#xff09;,任务调度 元数据管理: 业务系统管理/数据源管理/数据表管理/字段管理 数据源,元数据,数据授权,变更记…

基于Wireshark实现对FTP的抓包分析

基于Wireshark实现对FTP的抓包分析 前言一、虚拟机Win10环境配置二、FileZilla客户端的安装配置下载FileZilla客户端安装FileZilla 三、FileZilla Server安装下载FileZilla Server安装 四、实现对FTP的抓包前置工作实现抓包完成抓包 前言 推荐一个网站给想要了解或者学习人工智…