3

私はこの設定の解決策を見つけようとしています:

単一のAndroidデバイスがあり、複数のシリアル組み込みデバイスに接続したい...

これが、Bluetoothソケットを取得するための「通常の」方法を使用して、すべてのデバイスで機能するわけではありません。機能している間は、複数のデバイスに接続し、複数のデバイスとの間でデータを送受信できます。

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);
    }
}

そして、これが問題です。「通常」の方法が機能しない電話では、「回避策」の方法が単一の接続のソリューションを提供します。私は広範囲にわたって検索しましたが zipを思いつきました。

回避策の問題は最後のリンクに記載されています。両方の接続が同じポートを使用します。これにより、ブロックが発生し、両方の組み込みデバイスが実際にデータを送信できますが、Androidでは処理されません。組み込みデバイスは、Androidから送信されたデータを受信できます。

誰かが以前にこれを処理しましたか?

ここにもう少しリファレンスがあります、

アップデート:

これに続い(以前に投稿した)、mPortにチャンスを与え、おそらく他のポートインデックスと、他のデバイスがそれらを管理する方法を確認したいと思いました。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   

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)   

誰もがいくつかの洞察を持っています...

4

1 に答える 1

0

うわー、これが1つの大きな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);
    }

}

そして、パケットが完了するたびに、次のスレッドがパケットの解析を実行するために入る必要があります。

私の推測では、ポートに何らかのロックがあり、実装とともに2番目のスレッドが無期限にブロックされ、スレッドごとに異なるインスタンスへの解析を削除すると、問題は解決しました。

この洞察は、 mPortリンクの男であるDanielKnoppelに触発されました。

ダニエルありがとう!

于 2012-04-14T23:22:50.097 に答える