蓝牙(一)蓝牙设置详解

news/2024/11/20 4:19:42/

一.蓝牙相关的类

    1)BluetoothSettings.java

            该类是蓝牙配置和连接管理界面,就是咱们常见的蓝牙界面。它管理着蓝牙界面的加载,蓝牙搜索,蓝牙连接,蓝牙重命名等管理功能。(顺便借用一下大牛做的图片:https://www.cnblogs.com/dixonyy/p/4246057.html)


    2)BluetoothEnable.java

            该类是蓝牙辅助类,用来管理蓝牙的开和关以及蓝牙状态的标题显示。如打开或关闭蓝牙的switchbar的状态和文本显示。

    3)DeviceListPreferenceFragment.java

            该类是BluetoothSettings类的父类,是一个抽象类,该类包含了用于保存蓝牙设备的链表以及蓝牙。还包含蓝牙设备的一些回调方法。例如,蓝牙设备的删除、扫描状态的改变、蓝牙状态的改变等回调方法的实现。(回调接口所在的类:BluetoothCallback.java)

final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =

            new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();

该变量保存的是用于显示的蓝牙设备集合,可以删除或添加相应的蓝牙设备。

    4)CachedBluetoothDevice.java

            缓存蓝牙设备,该类代表了一个远程设备,它包含了蓝牙设备的一些属性(例如蓝牙地址,名字,信号强度等)。该类还可以进行蓝牙设备的连接、配对、断开连接等功能。

    5)BluetoothDevice.java

            该类也代表了一个远程设备,但是与上面不同的是就相当与你买了一个水杯,水杯就是BluetothDevice,用包装盒包裹起来的就是CachedBluetoothDevice。(个人比喻,有什么不对的可以指点改正,谢谢!)

    6)BluetoothDevicePreference.java

            该类是在设置界面显示蓝牙设备的偏好类型。点击界面上的配对、连接、断开就是在这操作的。

    7)BluetoothAdapter.java

            蓝牙适配器,是蓝牙的总中枢,是蓝牙的起点。要想使用蓝牙必须要开启或关闭,它就是蓝牙的总开关。该类让你执行基本的蓝牙任务,例如:初始化发现设别,查询绑定/配对的设备,使用蓝牙MAC地址实例化一个BLuetoothDevice,创建一个BLuetoothServerSocket来监听来自其它蓝牙设备的请求连接,开始扫描蓝牙低功耗设备等等。

    8)蓝牙事件管理BluetoothEventManager.java

            首先这里注册一个事件接收广播mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter);,用于接收底层驱动发来的广播。然后根据不同的action分发给不同的handler处理。这里的handler都需要通过addHandler函数保存到mHandlerMap中。然后在Handler中调用回调BluetoothCallback(接口),来交给ui上层处理。当然这里继承了BluetoothCallback接口的回调都是事先注册了的registerCallback。在设置中是DeviceListPreferenceFragment注册了。

    9)LocalBluetoothAdapter.java

            蓝牙接口适配为本地的蓝牙接口适配器,为应用提供接口,同时调用BluetoothAdapter的接口,起到应用和底层的适配作用。

    10)CachedBluetoothDeviceManager.java

           该类负责管理蓝牙的缓存(已配对的设备和搜索到的设备)主要都保存在List<CachedBluetoothDevice> mCachedDevices中

11)LocalBluetoothProfileManager.java

            该类提供访问有效的蓝牙协议对象LocalBluetoothProfile  

二.蓝牙流程

1.开启关闭蓝牙

    1)开启过程

        开启和关闭蓝牙的switchbar的监听状态存在与BluetoothEnable类中,当打开switchbar时           

@Overridepublic void onSwitchChanged(Switch switchView, boolean isChecked) {// Show toast message if Bluetooth is not allowed in airplane modeif (isChecked &&!WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();// Reset switch to offswitchView.setChecked(false);}MetricsLogger.action(mContext, MetricsLogger.ACTION_BLUETOOTH_TOGGLE, isChecked);if (mLocalAdapter != null) {
            //若isChecked为true,说明要开启蓝牙mLocalAdapter.setBluetoothEnabled(isChecked);}mSwitch.setEnabled(false);}
public void setBluetoothEnabled(boolean enabled) {boolean success = enabled? mAdapter.enable(): mAdapter.disable();if (success) {setBluetoothStateInt(enabled? BluetoothAdapter.STATE_TURNING_ON: BluetoothAdapter.STATE_TURNING_OFF);} else {if (Utils.V) {Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +"success for enabled: " + enabled);}syncBluetoothState();}}

--》BluetoothAdapter.enable()-->BluetoothManagerService.enable()

到了BluetoothManagerService就有点麻烦了

BluetoothManagerService.enable()

 public boolean enable() {if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&(!checkIfCallerIsForegroundUser())) {Log.w(TAG,"enable(): not allowed for non-active and non system user");return false;}mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,"Need BLUETOOTH ADMIN permission");if (DBG) {Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +" mBinding = " + mBinding);}synchronized(mReceiver) {mQuietEnableExternal = false;mEnableExternal = true;// waive WRITE_SECURE_SETTINGS permission checksendEnableMsg(false);}if (DBG) Log.d(TAG, "enable returning");return true;}

BluetoothManagerService.sendEnableMsg()发送一个handler开启蓝牙的消息

private void sendEnableMsg(boolean quietMode) {mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,quietMode ? 1 : 0, 0));}
BluetoothManagerService.handler
case MESSAGE_ENABLE:if (DBG) {Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);}mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);mEnable = true;handleEnable(msg.arg1 == 1);break;

BMS.handleEnable() 只取了部分开启蓝牙的代码

//Enable bluetoothtry {if (!mQuietEnable) {
                        //开启蓝牙if(!mBluetooth.enable()) {Log.e(TAG,"IBluetooth.enable() returned false");}}else {if(!mBluetooth.enableNoAutoConnect()) {Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");}}} catch (RemoteException e) {Log.e(TAG,"Unable to call enable()",e);}

接下来又调用了IBluetooth.enable(),具体实现是在AdapterService中,进而调用了AdapterService.enable()-->enable(boolean),代码如下:

public synchronized boolean enable(boolean quietMode) {enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);mQuietmode = quietMode;Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);mAdapterStateMachine.sendMessage(m);return true;}

接下来就到状态机AdapterState了,下面对BLE_TURN_ON消息进行处理

 case BLE_TURN_ON: notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);mPendingCommandState.setBleTurningOn(true);transitionTo(mPendingCommandState);sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);adapterService.BleOnProcessStart();break;

蓝牙开启之后,状态肯定变化了,所以也要发送一个广播,通知调用蓝牙的地方告诉它蓝牙状态已经改变,快做其它处理吧

private void notifyAdapterStateChange(int newState) {AdapterService adapterService = mAdapterService;AdapterProperties adapterProperties = mAdapterProperties;if ((adapterService == null) || (adapterProperties == null)) {errorLog("notifyAdapterStateChange after cleanup:" + newState);return;}int oldState = adapterProperties.getState();adapterProperties.setState(newState);infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState); adapterService.updateAdapterState(oldState, newState);}

下面就到了adapterservice里进行状态的更新了

void updateAdapterState(int prevState, int newState){if (mCallbacks !=null) {int n=mCallbacks.beginBroadcast();debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers.");for (int i=0; i <n;i++) {try { mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);}  catch (RemoteException e) {debugLog("updateAdapterState() - Callback #" + i + " failed ("  + e + ")");}}mCallbacks.finishBroadcast();}}

上面的加红的到底跳到哪个地方了哪?答案就是又回到BluetoothManagerService里了,这个回调主要实现的功能就是发送一个蓝牙状态改变的广播。

private final IBluetoothCallback mBluetoothCallback =  new IBluetoothCallback.Stub() {@Overridepublic void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);mHandler.sendMessage(msg);}};

懒得做时序图了,顺便再借用以下别人的。


                                   蓝牙开启时序图     

好了,蓝牙开启的部分已经结束了。通过上面的流程代码和时序图相信大家基本上能够搞清楚了。


2)蓝牙关闭流程

这个就不贴代码详细介绍了,基本的流程和蓝牙开启基本上都是一个样,请自行分析源代码。


这一节就介绍那么多,下一节将介绍蓝牙的配对、连接流程。




http://www.ppmy.cn/news/836853.html

相关文章

软件工程——第12章面向对象实现知识点整理

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1. 面向对象语言技术的特点&#xff1f; 2.选择面向对象程序设计语言时主要应该考虑哪些因素&#xff1f; 3.面向对象设计结果只能用面向对象语言实…

微信小程序音频播放问题createInnerAudioContext为何不调用onTimeUpdate

废话不多说&#xff0c;直接这么写就可以解决&#xff1a; innerAudioContext.play(); innerAudioContext.onCanplay(() > { innerAudioContext.play(); console.log(开始播放) }); innerAudioContext.onWaiting(() > { innerAudioCo…

Android上调用百度人脸识别接口

写了一个简单的调用百度人脸识别在线的JAVA接口&#xff0c;识别率挺高的&#xff0c;但是目前写得还不是很全面&#xff0c;然后打开相册选取图片那一部分&#xff0c;以及工具类代码&#xff0c;是有参考别人写的代码&#xff0c;具体是摘自哪里之前没有保存。 这里贴一些主…

Android 人脸识别了解一下 (中)

转载请注明作者及出处&#xff1a;https://www.jianshu.com/p/b41f64389c21 [25]——Android 人脸识别了解一下 &#xff08;上&#xff09; 在上文中我大致的介绍了官方 Demo 中人脸注册的流程&#xff0c;本文我们接着来看看&#xff0c;在完成了人脸注册之后我们该如何识别…

Adnroid 使用安卓自带的人脸识别API

缺点是精度不高&#xff0c;识别信息很少&#xff0c;只有眼睛的识别 MainActivity.java import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import and…

基于Android平台实现人脸识别

前言 在深度学习出现后&#xff0c;人脸识别技术才真正有了可用性。这是因为之前的机器学习技术中&#xff0c;难以从图片中取出合适的特征值。轮廓&#xff1f;颜色&#xff1f;眼睛&#xff1f;如此多的面孔&#xff0c;且随着年纪、光线、拍摄角度、气色、表情、化妆、佩饰挂…

安卓人脸检测之FaceDetector

最近看到一个APP的头像上传时&#xff0c;如果你设置的图片里面没有人脸&#xff0c;或者有两张以及以上人脸的时候&#xff0c;会提示你图片不符合规范&#xff0c;让你重新设置&#xff0c;这样是为了确保用户的头像是人&#xff01; 然后我就在网上查看了一下资料&#xff0…

人脸识别(识别程序)

系列文章目录 人脸采集 数据训练 代码思路 一、pandas是什么&#xff1f; 示例&#xff1a;pandas 是基于NumPy 的一种工具&#xff0c;该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入代码库 import cv2获取人脸识别对象 # 获取人脸识别对象 recognizer …