将Android设备连接到多个蓝牙串行嵌入式对等设备

3
我正在寻找这个设置的解决方案:
我有一个单一的Android设备,我想连接多个串行嵌入式设备...
问题在于,使用“正常”的方式来检索蓝牙套接字,在所有设备上都无法工作,而当它确实工作时,我可以连接到多个设备,并发送和接收来自多个设备的数据。
public final synchronized void connect()
        throws ConnectionException {
    if (socket != null)
        throw new IllegalStateException("Error socket is not null!!");
    connecting = true;
    lastException = null;
    lastPacket = null;
    lastHeartBeatReceivedAt = 0;
    log.setLength(0);
    try {
        socket = fetchBT_Socket_Normal();
        connectToSocket(socket);
        listenForIncomingSPP_Packets();
        connecting = false;
        return;
    } catch (Exception e) {
        socket = null;
        logError(e);
    }
    try {
        socket = fetchBT_Socket_Workaround();
        connectToSocket(socket);
        listenForIncomingSPP_Packets();
        connecting = false;
        return;
    } catch (Exception e) {
        socket = null;
        logError(e);
    }
    connecting = false;
    if (socket == null)
        throw new ConnectionException("Error creating RFcomm socket for" + this);
}

private BluetoothSocket fetchBT_Socket_Normal()
        throws Exception {
    /* The getType() is a hex 0xXXXX value agreed between peers --- this is the key (in my case) to multiple connections in the "Normal" way */
    String uuid = getType() + "1101-0000-1000-8000-00805F9B34FB";

    try {
        logDebug("Fetching BT RFcomm Socket standard for UUID: " + uuid + "...");
        socket = btDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
        return socket;
    } catch (Exception e) {
        logError(e);
        throw e;
    }
}

private BluetoothSocket fetchBT_Socket_Workaround()
        throws Exception {
    Method m;
    int connectionIndex = 1;
    try {
        logDebug("Fetching BT RFcomm Socket workaround index " + connectionIndex + "...");
        m = btDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
        socket = (BluetoothSocket) m.invoke(btDevice, connectionIndex);
        return socket;
    } catch (Exception e1) {
        logError(e1);
        throw e1;
    }
}

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

这里的问题是,在手机上“正常”的方法行不通,而“解决方法”为单个连接提供了解决方案。我已经搜索过很多地方什么也没有找到。

解决方法的问题在最后一个链接中提到,两个连接使用同一端口,这在我的情况下会导致阻塞,其中嵌入式设备都可以发送数据,但Android没有对其进行处理,而两个嵌入式设备都可以接收从Android发送的数据。

有人之前处理过这个问题吗?

这里有更多的参考资料 这里

更新:

在我之前发布这个之后,我想给mPort一个机会,也许看看其他端口指数以及其他设备如何管理它们,结果我发现在BluetoothSocket对象中的字段不同,尽管它是相同的类FQN:

来自HTC Vivid 2.3.4的详细信息,使用“workaround”技术:

Socket类类型为:[android.bluetooth.BluetoothSocket]

mSocket BluetoothSocket  (id=830008629928)  
    EADDRINUSE          98  
    EBADFD              77  
    MAX_RFCOMM_CHANNEL  30  
    TAG                 "BluetoothSocket" (id=830002722432) 
    TYPE_L2CAP          3   
    TYPE_RFCOMM         1   
    TYPE_SCO            2   
    mAddress            "64:9C:8E:DC:56:9A" (id=830008516328)   
    mAuth               true    
    mClosed             false   
    mClosing            AtomicBoolean  (id=830007851600)    
    mDevice             BluetoothDevice  (id=830007854256)  
    mEncrypt            true    
    mInputStream        BluetoothInputStream  (id=830008688856) 
    mLock               ReentrantReadWriteLock  (id=830008629992)   
    mOutputStream       BluetoothOutputStream  (id=830008430536)    
    **mPort             1** 
    mSdp                null    
    mSocketData         3923880 
    mType               1   

来自LG-P925 2.2.2的详细信息,使用“normal”技术:

Socket类的类型是:[android.bluetooth.BluetoothSocket]

mSocket BluetoothSocket  (id=830105532880)  
    EADDRINUSE          98  
    EBADFD              77  
    MAX_RFCOMM_CHANNEL  30  
    TAG                 "BluetoothSocket" (id=830002668088) 
    TYPE_L2CAP          3   
    TYPE_RFCOMM         1   
    TYPE_SCO            2   
    mAccepted           false   
    mAddress            "64:9C:8E:B9:3F:77" (id=830105544600)   
    mAuth               true    
    mClosed             false   
    mConnected          ConditionVariable  (id=830105533144)    
    mDevice             BluetoothDevice  (id=830105349488)  
    mEncrypt            true    
    mInputStream        BluetoothInputStream  (id=830105532952) 
    mLock               ReentrantReadWriteLock  (id=830105532984)   
    mOutputStream       BluetoothOutputStream  (id=830105532968)    
    mPortName           "" (id=830002606256)    
    mSocketData         0   
    mSppPort            BluetoothSppPort  (id=830105533160) 
    mType               1   
    mUuid               ParcelUuid  (id=830105714176)   

有人有一些见解...


我尝试了各种随机端口号,从1到5,但都没有成功。 - TacB0sS
我还在这里映射了我在开发Android蓝牙功能时遇到的其他一些问题:http://www.blogger.com/blogger.g?blogID=1531299241496277633#allposts/postNum=0 - TacB0sS
1个回答

0

哇,每次这都让我感到非常困惑?

这是一个竞态条件问题,显然在一个版本的Android上可以工作,而在另一个版本上则不行。在Android端,我正在解析从套接字接收到的数据包:

public class SocketListener
        implements Runnable {

    private boolean stop;

    private OnIncomingPacketListener packetListener;

    @Override
    public void run() {
        InputStream inputStream;
        try {
            stop = false;
            inputStream = socket.getInputStream();
            while (!stop) {
                Packet packet = Packet.getPacket(inputStream);
                lastPacket = packet;
                if (packet.getDescriptor() == Packet.HeartBeat)
                    lastHeartBeatReceivedAt = System.currentTimeMillis();
                else if (packet.getDescriptor() == Packet.LogEntry)
                    log.append(((LogEntryPacket) packet).getLogEntry());
                synchronized (this) {
                    if (packetListener != null)
                        packetListener.onIncomingData(EmbeddedDevice.this, packet);
                }
            }
        } catch (IOException e) {
            logError("----- BLUETOOTH IO ERROR -----\n @: " + EmbeddedDevice.this, e);

            return;
        } catch (RuntimeException e) {
            logError("----- BLUETOOTH LISTENER ERROR -----\n @: " + EmbeddedDevice.this, e);
            throw e;
        } finally {
            socketListeningThread = null;
        }
    }
}

Packet.getPacket(inputStream) 函数的位置:

public static synchronized Packet getPacketInstance(InputStream inputStream)
        throws IOException {
    int data = inputStream.read();
    Packet type = null;
    for (Packet packetType : values())
        if (packetType.packetType == data) {
            type = packetType;
            break;
        } // race condition here...
    if (type == null)
        throw new IllegalArgumentException("Unknown packet type: " + data);
    try {
        Packet packet = type.incomingPacketType.newInstance();
        packet.setDescriptor(type);
        packet.readPacketData(inputStream);
        return packet;
    } catch (IOException e) {
        throw e;
    } catch (Exception e) {
        throw new IllegalStateException("Error instantiating type: " + type.incomingPacketType.getName(), e);
    }

}

每当一个数据包完成时,下一个线程应该进入执行它的解析。
我猜测端口上有某种锁定机制,加上我的实现导致第二个线程无限期地阻塞,一旦我将解析移动到每个线程的不同实例中,问题就消失了。
这个想法是受到来自mPort链接的Daniel Knoppel的启发。
谢谢你,Daniel!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接