Android 蓝牙配对Settings应用里面的简要流程记录
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)这是一个Activityandroid: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";@Overridepublic 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)拉起 BluetoothPairingServiceintent.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() {@Overridepublic 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();}}}};@Overrideprotected 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 {//里面的代码基本都是对话框界面和相关逻辑的控制
...//点击取消和确认配对情况的回调@Overridepublic 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 mFocmFocusedApp=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 mFocmFocusedApp=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了:
<receiverandroid:name=".accessories.BluetoothPairingRequest"android:exported="true"><intent-filter><action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/></intent-filter></receiver><activityandroid: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 {@Overridepublic 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.javapackages\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
相关文章:
Android 蓝牙配对Settings应用里面的简要流程记录
Android 蓝牙配对Settings应用里面的简要流程记录 文章目录 Android 蓝牙配对Settings应用里面的简要流程记录一、前言二、Settings蓝牙配对的关键代码1、接收蓝牙请求的地方 AndroidManifest.xml2、BluetoothPairingRequest3、BluetoothPairingService4、BluetoothPairingDial…...
shell编程基础(第18篇:更多的文件操作命令介绍)
前言 对于文件来说,除了它的文件内容之外,就是对其文件本身的操作,比如我们想要重命名文件、移动文件、复制文件、已经获取文件所在目录,文件名等操作,今天一起学习更多的文件操作相关的命令 basename 用于获取文件名…...
java如何提取字符串的每一个字符
java如何提取字符串每一个字符并转换为一个字符数组 这里需要用到toCharArray()语句 语法格式是 str.toCharArray(); 其中 str是字符串 示例代码如下 public class StringToArray {public static void main(String[] args) {String str"这是一个字符串";char[…...
LVS负载均衡:理解IPVS和IPVSADM的内部工作原理
LVS 负载均衡工作模式 LVS(Linux Virtual Server) 共有三种工作模式:DR、Tunnel、NAT。 DR(Direct Routing): 技术原理:DR模式下,LVS调度器接收到请求后,直接通过MAC地址…...
c语言回顾-结构体
前言 在前面的学习中,我们知道C语言提供了许多内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的。当我们想描述学生,描述一本书,这时单一的内置类型是不行的。描述一个…...
stable diffusion最全插件大全,新手必备指南
Stable diffusion30个必备插件推荐,给我点个赞吧,兄弟们 1,ComfyUI,SD扩展里面直接搜索就行, ComfyUI 是一个基于节点操作的UI界面,玩过建模的更容易学 安装后大概是这样的 评价:comfyui,更适…...
大模型开发LangChain简介
LangChain 是一个用于构建大型语言模型 (LLM) 驱动应用程序的开发框架。它提供了强大的工具和功能,帮助开发者更高效地使用语言模型来构建复杂的应用程序。 LangChain 的主要功能和特点 1、模块化设计: LangChain 采用模块化设计,分为多个…...
Camtasia Studio 2024软件最新版下载【安装详细图文教程】
Camtasia是美国TechSmith公司出品的一款集电脑屏幕录制、视频剪辑为一体的软件套装。同时包含Camtasia 录制器、Camtasia Studio(编辑器)、Camtasia 菜单制作器、Camtasia 剧场、Camtasia 播放器和Screencast的内置功能。 安 装 包 获 取 地 址&#x…...
抖音视频素材在哪找无版权?免版权可以剪辑视频素材网站分享
在抖音视频制作中,素材的选择至关重要。今天,我就为大家推荐几个宝藏网站,帮你找到既好用又无版权纠纷的视频素材。无论你是新手还是老手,这些网站都能满足你的需求。 蛙学府 首先推荐的是蛙学府。这个网站提供丰富的视频素材&am…...
Dubbo-使用zookeeper作为注册中心时节点的概述
本文内容很容易理解,会阐述当dubbo使用zookeeper作为注册中心时候,zookeeper节点是什么样子的 本文的代码使用的dubbo版本是2.7.x,几年前的版本了,但是不影响探究 首先我们创建一个简单的maven项目,然后写出一段dubb…...
秋招突击——第四弹——Java的SSN框架快速入门——Maven
文章目录 引言Maven分模块开发与设计分模块开发的过程 依赖管理可选依赖与排除依赖 继承与聚合聚合继承 属性和版本管理属性扩大集中管理的范围版本管理 多环境开发多环境开发 私服简介安装私服资源操作流程分析上传和下载 总结 引言 前一个部分花了太多时间,后续得…...
【Python】数据处理:CSV文件操作
CSV 文件(Comma-Separated Values,逗号分隔值文件)是一种常见的文本文件格式,用于存储表格数据。它的特点是用逗号或其他特定字符(如分号、制表符等)来分隔不同的字段,每行代表表格中的一条记录…...
SpringBoot集成Elasticsearch实例
SpringBoot项目集成Elasticsearch实例 导包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>配置es连接 spring:data:elasticsearch:cluster…...
2024.ZCPC.M题 计算三角形个数
题目描述: 小蔡有一张三角形的格子纸,上面有一个大三角形。这个边长为 的大三角形, 被分成 个边长为 1 的小三角形(如图一所示)。现在,小蔡选择了一条水平边 删除(如图二所示),请你找出图上剩余…...
Java常见设计模式入门与实践
设计模式是软件开发中被反复应用的、为解决特定问题而总结出的最佳实践。它们提供了开发可重用、灵活和高效软件系统的方法。在Java中,设计模式可以帮助开发者编写更高质量的代码。以下是Java中一些常用设计模式的入门介绍及其实践示例。 1. 单例模式 (Singleton P…...
110.平衡二叉树
给定一个二叉树,判断它是否是 平衡二叉树 题解:平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。可以采用递归遍历每一个节点,得到其高度,在判断高度时不可避免的要用到其左右子树的高度,所以可以顺便判断出…...
字符串数组——传递文本的不同方法实例
一、实例化一个文本并在文本上直接显示接收的信息 1、制作一个预制体 (1) UI-Text (TMP),TitleText (2) 给Text (TMP)添加Recipients.cs组件 using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine;public class Recipi…...
JDBC简介
JDBC最基本的知识点要求理解并会使用下边的两个案例即可: 前言: Jdbc操作步骤简析: 1.Connection connDriverManager.getConnection(url,账号,密码):用DriverManager类的连接方法根据url账号密码连接数据库…...
RK3568平台(触摸篇)触摸屏基本原理
一.触摸屏概述 触摸屏作为一种新的输入设备,它是目前最简单、方便、自然的一种人机交互方式。 触摸屏又称为“触控屏”、“触控面板”,是一种可接收触头等输入讯号的感应式液晶显示装置;当接触了屏幕上的图形按钮时,屏幕上的触觉…...
【太原理工大学】软件系统安全—分析题
OK了,又是毫无准备的一场仗,我真是ありがとうございます 凸^o^凸 根据前几年传下来的信息,所谓“分析”,就是让你根据情节自行设计,例如如何设计表单等,这类多从实验中出,王老师强调好好做实验一…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
