蓝牙(一)蓝牙设置详解

一.蓝牙相关的类

    1)BluetoothSettings.java

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

蓝牙(一)蓝牙设置详解_第1张图片

    2)BluetoothEnable.java

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

    3)DeviceListPreferenceFragment.java

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

final WeakHashMap mDevicePreferenceMap =

            new WeakHashMap();

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

    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 mCachedDevices中

11)LocalBluetoothProfileManager.java

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

二.蓝牙流程

1.开启关闭蓝牙

    1)开启过程

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

@Override
    public void onSwitchChanged(Switch switchView, boolean isChecked) {
        // Show toast message if Bluetooth is not allowed in airplane mode
        if (isChecked &&
                !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
            Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
            // Reset switch to off
            switchView.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 check
            sendEnableMsg(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 bluetooth
                try {
                    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  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() {
        @Override
        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
            mHandler.sendMessage(msg);
        }
    };

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

蓝牙(一)蓝牙设置详解_第2张图片

                                   蓝牙开启时序图     

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


2)蓝牙关闭流程

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

蓝牙(一)蓝牙设置详解_第3张图片

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



你可能感兴趣的:(蓝牙)