Android 蓝牙遥控器的连接

项目是TV端的,产品要求不经过设置界面,开机进入引导页,自动搜索蓝牙遥控器并且建立连接。
刚开始接手的时候以为会很快完成,无非就是调用API吗?可是事实不是这样,前后花了一些时间,才解决。
好了,当时尝试了Socket连接以及低功耗连接BLE,事实证明都不可行,后来就在想设置界面是怎么连接的呢,终于找到了答案。
蓝牙设置界面入口在BluetoothSettings.java,这个BluetoothSettings继承自DeviceListPreferenceFragment.java。点击某个搜索到的蓝牙列表项之后,走的流程如下:

 void onClicked() {
        int bondState = mCachedDevice.getBondState();
        if (mCachedDevice.isConnected()) {
            askDisconnect();
        } else if (bondState == BluetoothDevice.BOND_BONDED) {
            mCachedDevice.connect(true);
        } else if (bondState == BluetoothDevice.BOND_NONE) {
            pair();
        }
    }

在这个方法里面对当前蓝牙设备状态进行判断,如果没有绑定上,去pair,绑定上了
进行连接,调用的mCachedDevice.connect(true);这个mCachedDevice是
/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
我们看下其中具体实现:

  public void connect(boolean connectAllProfiles) {
        //如果没有连接上,返回
        if (!ensurePaired()) {
            return;
        }

        mConnectAttempted = SystemClock.elapsedRealtime();
        connectWithoutResettingTimer(connectAllProfiles);
    }

具体实现在connectWithoutResettingTimer方法中,我们看最终其调用的方法:

  synchronized void connectInt(LocalBluetoothProfile profile) {
        if (!ensurePaired()) {
            return;
        }
        if (profile.connect(mDevice)) {
            if (Utils.D) {
                Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));
            }
            return;
        }
        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
    }

这个profile是什么呢?它的意义很大,其实代表我们蓝牙协议具体实现接口,蓝牙连接的设备有很多种,我们的蓝牙遥控器属于Hid设备,是其中之一,HidProfile是Hid连接协议,一层层查找,最终找到蓝牙连接的最终实现在framework/base/core/java/android/bluetooth/BluetoothInputDevice.java。

    /**
     * Initiate connection to a profile of the remote bluetooth device.
     *
     * 

The system supports connection to multiple input devices. * *

This API returns false in scenarios like the profile on the * device is already connected or Bluetooth is not turned on. * When this API returns true, it is guaranteed that * connection state intent for the profile will be broadcasted with * the state. Users can get the connection state of the profile * from this intent. * *

Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device * @return false on immediate error, * true otherwise * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); Log.d(TAG,"mService is null ?"+ mService==null); if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); return false; }

从该方法的注释中就可以看出,该方法就是用来连接Hid蓝牙设备的,好了,所以我们最终只要把这个类的方法调用起来就可以了,这个类直接SDK是获取不到的,不过也不要直接反射这个类,我们可以通过BluetoothAdapter的getProfileProxy方法获取到该类对象。
这里写图片描述

在其回调中,反射调用connect方法。
Android 蓝牙遥控器的连接_第1张图片

好了,到这里就大功告成啦~~

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