2012-04-14 58 views
3

我試圖找到這個設置的解決方案:連接Android設備到多個藍牙系列嵌入式同行

我有一個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); 
    } 
} 

這裏是一回事,而在其「正常」的方式不起作用手機,「解決方法」的方式提供了一個連接的解決方案。我有searchedfarandwide,但想出了zip。

解決方法的問題在最後一個鏈接中提到,兩個連接使用相同的端口,在我的情況下,這會導致一個塊,其中兩個嵌入式設備實際上可以發送數據,但尚未在Android,而這兩個嵌入式設備都可以接收Android發送的數據。

以前有人處理過嗎?

有更多的參考here

UPDATE:

this(我前面貼)我想給M端口一個機會,也許看其他端口索引,並其他設備如何管理它們,並且我發現在兩種情況下,BluetoothSocket對象中的字段是不同的,而它們是相同的類FQN:

來自HTC Vivid 2.3.4的缺陷使用「解決方法」技術:

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 

Detils從LG-P925 2.2.2,採用 「正常」 的工藝:

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) 

任何人有一些見解...

+0

我試過各種隨機端口號,1-5,沒有任何工作。 – TacB0sS 2012-04-14 02:20:15

+0

我還繪製了一些我在Android藍牙功能中遇到的其他問題:http://www.blogger.com/blogger.g?blogID=1531299241496277633#allposts/postNum=0 – TacB0sS 2012-04-14 11:54:16

回答

0

WOW,這每次都會讓我失望的是一個大的WTF?

這是一個競態條件問題,它顯然適用於一個版本的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); 
    } 

} 

而每一個數據包完成時,下一個線程應該有去執行解析。

我的猜測是在端口上有某種鎖定,與我的實現一起導致第二個線程無限期阻塞,一旦我將每個線程的解析分離到不同的實例,問題就解決了。

這一見解是由丹尼爾Knoppel,從M端口鏈接的傢伙的啓發。

謝謝丹尼爾!