且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

安卓4.0+蓝牙连接错误到嵌入式设备:"被拒绝的权限和QUOT;

更新时间:2023-01-06 22:21:46

在调查此事的很长很长一段时间,我发现了一个错误的原因......一些汽车蓝牙对等不启用Android设备/不允许的。

因此​​,显然除了两个连接方法,也有两个蓝牙适配器实现的方法,一将抛出意图要求系统打开适配器,另一个是调用到BluetoothAdapter.enable( )法,使蓝牙默默地

第一种方法,会弹出一个确认对话框,并要求用户交互,而另一个没有,虽然没有显示蓝牙启用确认对话框,也对等确认没有显示出来,从而导致连接错误。

使用的第一个适配器实现的方法解决这个问题的大部分设备,如的Nexus 7,三星S3,和其他几个人,但在某些设备上仍然有一个问题,我真的不知道为什么,但是这是好多了,因为很多设备目前正与新的实现。

I have the following setup:

An Android device uses a 'Client' socket to connect to a remote embedded device, The Android application uses the following code snippet to connect to the embedded device.

On the embedded device uses MindTree BT stack, where server serial socket is prepared according to some properties in the device, which the Android application is familiar with, the connection defined on the embedded device, is not secured!!

The combination of both applications works on:

  • 2 LG phones different models (version code < 10 uses the "Normal method")
  • 2 HTC's different models (version code < 10 uses the "Workaround method")
  • Pantech Tablet (version code < 13 uses the "Workaround method")

Today, I've tried the application on Samsung S3, Motorola MB886, and a Nexus 7... All resulted in a "Permission Denied" when calling to socket.connect()... (I have the proper permissions in the manifest, otherwise it would not work on the other devices.)

All the new devices I've tested on are version code > 4.0, so I'm wondering:

Does anyone know about any changes in the API? Perhaps Android 4.0+ forces security?

It seem that the error occur in the Bonding state, since I can see on the embedded program logs...

Any insights?

The code:

public final synchronized int connectToDevice(int connectingMethod)
        throws BluetoohConnectionException {
    if (socket != null)
        throw new BadImplementationException("Error socket is not null!!");
    connecting = true;
    logInfo("+---+ Connecting to device...");

    try {
        lastException = null;
        lastPacket = null;
        if (connectingMethod == BluetoothModule.BT_StandardConnection
                || connectingMethod == BluetoothModule.BT_ConnectionTBD)
            try {

                socket = fetchBT_Socket_Normal();
                connectToSocket(socket);
                listenForIncomingSPP_Packets();
                onConnetionEstablished();
                return BluetoothModule.BT_StandardConnection;
            } catch (BluetoohConnectionException e) {
                socket = null;
                if (connectingMethod == BluetoothModule.BT_StandardConnection) {
                    throw e;
                }
                logWarning("Error creating socket!", e);
            }
        if (connectingMethod == BluetoothModule.BT_ReflectiveConnection
                || connectingMethod == BluetoothModule.BT_ConnectionTBD)
            try {
                socket = fetchBT_Socket_Reflection(1);
                connectToSocket(socket);
                listenForIncomingSPP_Packets();
                onConnetionEstablished();
                return BluetoothModule.BT_ReflectiveConnection;
            } catch (BluetoohConnectionException e) {
                socket = null;
                if (connectingMethod == BluetoothModule.BT_ReflectiveConnection) {
                    throw e;
                }
                logWarning("Error creating socket!", e);
            }
        throw new BluetoohConnectionException("Error creating RFcomm socket for BT Device:" + this
                + "\n BAD connectingMethod==" + connectingMethod);
    } finally {
        connecting = false;
    }
}

protected void onConnetionEstablished() {
    logInfo("+---+ Connection established");
}

private synchronized void listenForIncomingSPP_Packets() {
    if (socketListeningThread != null)
        throw new BadImplementationException("Already lisening on Socket for BT Device" + this);
    logInfo("+---+ Listening for incoming packets");
    socketListeningThread = new Thread(socketListener, "Packet Listener - " + bluetoothDevice.getName());
    socketListeningThread.start();
}

private BluetoothSocket fetchBT_Socket_Normal()
        throws BluetoohConnectionException {
    try {
        logInfo("+---+ Fetching BT RFcomm Socket standard for UUID: " + uuid + "...");
        return bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
    } catch (Exception e) {
        throw new BluetoohConnectionException("Error Fetching BT RFcomm Socket!", e);
    }
}

private BluetoothSocket fetchBT_Socket_Reflection(int connectionIndex)
        throws BluetoohConnectionException {
    Method m;
    try {
        logInfo("+---+ Fetching BT RFcomm Socket workaround index " + connectionIndex + "...");
        m = bluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
        return (BluetoothSocket) m.invoke(bluetoothDevice, connectionIndex);
    } catch (Exception e) {
        throw new BluetoohConnectionException("Error Fetching BT RFcomm Socket!", e);
    }
}

private void connectToSocket(BluetoothSocket socket)
        throws BluetoohConnectionException {
    try {
        logInfo("+---+ Connecting to socket...");
        socket.connect();
        logInfo("+---+ Connected to socket");
    } catch (IOException e) {
        try {
            socket.close();
        } catch (IOException e1) {
            logError("Error while closing socket", e1);
        } finally {
            socket = null;
        }
        throw new BluetoohConnectionException("Error connecting to socket with Device" + this, e);
    }
}

After very long long time of investigating the matter I've found one reason for the error... on some Android devices the auto Bluetooth peering is not enabled/allowed.

So, apparently except for two connection method, there are also two Bluetooth adapter enabling method, one would be to throw an intent to ask the system to turn the adapter on, and the other is to call onto the BluetoothAdapter.enable() method, which enables the Bluetooth silently.

The first method, pops a confirmation dialog, and require user interaction while the other does not, and while not showing the Bluetooth enabling confirmation dialog, also the peering confirmation is not shown, which causes the connection error.

Using the first adapter enabling method solves the problem on most of the devices, like the Nexus 7, Samsung S3, and a few others, but on some devices there is still an issue, and I'm not really sure why, but this is much better since many devices are now working with the new implementation.