Monodroid中的蓝牙插座错误

时间:2016-03-31 07:53:18

标签: c# android bluetooth xamarin.android

我有一个蓝牙设备,我想用我的智能手机连接,但这并不重要,它总会出现同样的错误:Java.IO.IOException: read failed, socket might closed or timeout, read ret: -1

我已经在Stackoverflow上阅读了一些内容,但这些答案并不那么明确。是否有人有这方面的经验?

错误将显示在以下行:socket.Connect();

代码下方(我使用了Xamarin Android Connecting with bluetooth device的视频教程)。

BluetoothManager.cs

public class BluetoothManager
{
    private const string profile = "00001101-0000-1000-8000-E4121DB64549";
    private BluetoothDevice result;
    private BluetoothSocket socket;
    private BufferedReader reader;
    private System.IO.Stream mStream;
    private InputStreamReader mReader;

    public BluetoothManager()
    {
        reader = null;
    }

    private UUID GetProfileUUID()
    {
        return UUID.FromString(profile);
    }

    private void Close(IDisposable connObject)
    {
        if (connObject == null) return;
        try
        {
            connObject.Dispose();
        } catch (Exception ex)
        {
            throw ex;
        }
    }

    public String GetDataFromDevice()
    {
        return reader.ReadLine();
    }

    private void OpenDeviceConnection(BluetoothDevice bd)
    {
        try
        {
            socket = bd.CreateRfcommSocketToServiceRecord(GetProfileUUID());
            socket.Connect();
            mStream = socket.InputStream;
            mReader = new InputStreamReader(mStream);
            reader = new BufferedReader(mReader);
        } catch (IOException ex)
        {
            Close(socket);
            Close(mStream);
            Close(mReader);
            throw ex;
        }
    }

    public void GetDevice()
    {
        BluetoothAdapter btAdapter = BluetoothAdapter.DefaultAdapter;
        var devices = btAdapter.BondedDevices;
        if(devices != null && devices.Count > 0)
        {
            foreach (BluetoothDevice bd in devices)
            {
                if(bd.Name == "CONTROLLER")
                {
                    OpenDeviceConnection(bd);
                }
            }
        }
    }
}

InputModel.cs

public class InputModel
{
    private string data = null;

    public InputModel()
    {
        BluetoothManager bluetoothManager = new BluetoothManager();
        bluetoothManager.GetDevice();

        Thread thread = new Thread(() =>
        {
            while (true)
            {
                data = bluetoothManager.GetDataFromDevice();
            }
        });
        thread.IsBackground = true;
        thread.Start();
    }
}

我希望有人可以帮我解决这个问题!

3 个答案:

答案 0 :(得分:0)

请创建蓝牙服务器套接字

public class BluetoothService {

private static final String TAG = "Bluetooth Service";

// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "Bluetooth Secure";

// Unique UUID for this application
private static final UUID UUID_ANDROID_DEVICE =
        UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID UUID_OTHER_DEVICE =
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
private boolean isAndroid = BluetoothState.DEVICE_ANDROID;

// Constructor. Prepares a new BluetoothChat session
// context : The UI Activity Context
// handler : A Handler to send messages back to the UI Activity
public BluetoothService(Context context, Handler handler) {
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    mState = BluetoothState.STATE_NONE;
    mHandler = handler;
}


// Set the current state of the chat connection
// state : An integer defining the current connection state
private synchronized void setState(int state) {
    Log.d(TAG, "setState() " + mState + " -> " + state);
    mState = state;

    // Give the new state to the Handler so the UI Activity can update
    mHandler.obtainMessage(BluetoothState.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

// Return the current connection state. 
public synchronized int getState() {
    return mState;
}

// Start the chat service. Specifically start AcceptThread to begin a
// session in listening (server) mode. Called by the Activity onResume() 
public synchronized void start(boolean isAndroid) {
    // Cancel any thread attempting to make a connection
    if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

    setState(BluetoothState.STATE_LISTEN);

    // Start the thread to listen on a BluetoothServerSocket
    if (mSecureAcceptThread == null) {
        mSecureAcceptThread = new AcceptThread(isAndroid);
        mSecureAcceptThread.start();
        BluetoothService.this.isAndroid = isAndroid;
    }
}

// Start the ConnectThread to initiate a connection to a remote device
// device : The BluetoothDevice to connect
// secure : Socket Security type - Secure (true) , Insecure (false)
public synchronized void connect(BluetoothDevice device) {
    // Cancel any thread attempting to make a connection
    if (mState == BluetoothState.STATE_CONNECTING) {
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
    }

    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

    // Start the thread to connect with the given device
    mConnectThread = new ConnectThread(device);
    mConnectThread.start();
    setState(BluetoothState.STATE_CONNECTING);
}

/**
 * Start the ConnectedThread to begin managing a Bluetooth connection
 * @param socket  The BluetoothSocket on which the connection was made
 * @param device  The BluetoothDevice that has been connected
 */
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
        device, final String socketType) {
    // Cancel the thread that completed the connection
    if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

    // Cancel the accept thread because we only want to connect to one device
    if (mSecureAcceptThread != null) {
        mSecureAcceptThread.cancel();
        mSecureAcceptThread = null;
    }

    // Start the thread to manage the connection and perform transmissions
    mConnectedThread = new ConnectedThread(socket, socketType);
    mConnectedThread.start();

    // Send the name of the connected device back to the UI Activity
    Message msg = mHandler.obtainMessage(BluetoothState.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString(BluetoothState.DEVICE_NAME, device.getName());
    bundle.putString(BluetoothState.DEVICE_ADDRESS, device.getAddress());
    msg.setData(bundle);
    mHandler.sendMessage(msg);

    setState(BluetoothState.STATE_CONNECTED);
}

// Stop all threads
public synchronized void stop() {
    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }

    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }

    if (mSecureAcceptThread != null) {
        mSecureAcceptThread.cancel();
        mSecureAcceptThread.kill();
        mSecureAcceptThread = null;
    }
    setState(BluetoothState.STATE_NONE);
}

// Write to the ConnectedThread in an unsynchronized manner
// out : The bytes to write
public void write(byte[] out) {
    // Create temporary object
    ConnectedThread r;
    // Synchronize a copy of the ConnectedThread
    synchronized (this) {
        if (mState != BluetoothState.STATE_CONNECTED) return;
        r = mConnectedThread;
    }
    // Perform the write unsynchronized
    r.write(out);
}

// Indicate that the connection attempt failed and notify the UI Activity
private void connectionFailed() {
    // Start the service over to restart listening mode
    BluetoothService.this.start(BluetoothService.this.isAndroid);
}

// Indicate that the connection was lost and notify the UI Activity
private void connectionLost() {
    // Start the service over to restart listening mode
    BluetoothService.this.start(BluetoothService.this.isAndroid);
}

// This thread runs while listening for incoming connections. It behaves
// like a server-side client. It runs until a connection is accepted
// (or until cancelled)
private class AcceptThread extends Thread {
    // The local server socket
    private BluetoothServerSocket mmServerSocket;
    private String mSocketType;
    boolean isRunning = true;

    public AcceptThread(boolean isAndroid) {
        BluetoothServerSocket tmp = null;

        // Create a new listening server socket
        try {
            if(isAndroid)
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_ANDROID_DEVICE);
            else
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_OTHER_DEVICE);
        } catch (IOException e) { }
        mmServerSocket = tmp;
    }

    public void run() {
        setName("AcceptThread" + mSocketType);
        BluetoothSocket socket = null;

        // Listen to the server socket if we're not connected
        while (mState != BluetoothState.STATE_CONNECTED && isRunning) {
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }

            // If a connection was accepted
            if (socket != null) {
                synchronized (BluetoothService.this) {
                    switch (mState) {
                    case BluetoothState.STATE_LISTEN:
                    case BluetoothState.STATE_CONNECTING:
                        // Situation normal. Start the connected thread.
                        connected(socket, socket.getRemoteDevice(),
                                mSocketType);
                        break;
                    case BluetoothState.STATE_NONE:
                    case BluetoothState.STATE_CONNECTED:
                        // Either not ready or already connected. Terminate new socket.
                        try {
                            socket.close();
                        } catch (IOException e) { }
                        break;
                    }
                }
            }
        }
    }

    public void cancel() {
        try {
            mmServerSocket.close();
            mmServerSocket = null;
        } catch (IOException e) { }
    }

    public void kill() {
        isRunning = false;
    }
}


// This thread runs while attempting to make an outgoing connection
// with a device. It runs straight through
// the connection either succeeds or fails
private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    private String mSocketType;

    public ConnectThread(BluetoothDevice device) {
        mmDevice = device;
        BluetoothSocket tmp = null;

        // Get a BluetoothSocket for a connection with the
        // given BluetoothDevice
        try {
            if(BluetoothService.this.isAndroid)
                tmp = device.createRfcommSocketToServiceRecord(UUID_ANDROID_DEVICE);
            else
                tmp = device.createRfcommSocketToServiceRecord(UUID_OTHER_DEVICE);
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
        // Always cancel discovery because it will slow down a connection
        mAdapter.cancelDiscovery();

        // Make a connection to the BluetoothSocket
        try {
            // This is a blocking call and will only return on a
            // successful connection or an exception
            mmSocket.connect();
        } catch (IOException e) {
            // Close the socket
            try {
                mmSocket.close();
            } catch (IOException e2) { }
            connectionFailed();
            return;
        }

        // Reset the ConnectThread because we're done
        synchronized (BluetoothService.this) {
            mConnectThread = null;
        }

        // Start the connected thread
        connected(mmSocket, mmDevice, mSocketType);
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}

// This thread runs during a connection with a remote device.
// It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket, String socketType) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the BluetoothSocket input and output streams
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) { }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        byte[] buffer;
        ArrayList<Integer> arr_byte = new ArrayList<Integer>();

        // Keep listening to the InputStream while connected
        while (true) {
            try {
                int data = mmInStream.read();
                if(data == 0x0A) { 
                } else if(data == 0x0D) {
                    buffer = new byte[arr_byte.size()];
                    for(int i = 0 ; i < arr_byte.size() ; i++) {
                        buffer[i] = arr_byte.get(i).byteValue();
                    }
                    // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(BluetoothState.MESSAGE_READ
                            , buffer.length, -1, buffer).sendToTarget();
                    arr_byte = new ArrayList<Integer>();
                } else {
                    arr_byte.add(data);
                }
            } catch (IOException e) {
                connectionLost();
                // Start the service over to restart listening mode
                BluetoothService.this.start(BluetoothService.this.isAndroid);
                break;
            }
        }
    }

    // Write to the connected OutStream.
    // @param buffer  The bytes to write
    public void write(byte[] buffer) {
        try {/*
            byte[] buffer2 = new byte[buffer.length + 2];
            for(int i = 0 ; i < buffer.length ; i++) 
                buffer2[i] = buffer[i];
            buffer2[buffer2.length - 2] = 0x0A;
            buffer2[buffer2.length - 1] = 0x0D;*/
            mmOutStream.write(buffer);
            // Share the sent message back to the UI Activity
            mHandler.obtainMessage(BluetoothState.MESSAGE_WRITE
                    , -1, -1, buffer).sendToTarget();
        } catch (IOException e) { }
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
    }
}`

答案 1 :(得分:0)

我刚刚添加了GetUuids().ElementAt(0)来解决我的问题。见代码:

        var listDevices = bluetoothAdapter.BondedDevices;
        if (listDevices.Count > 0)
        {
            foreach (var btDevice in listDevices)
            {
                if (btDevice.Name == "CONTROLLER")
                {
                    UUID = btDevice.GetUuids().ElementAt(0);
                    deviceDictionary.Add(btDevice.Name, btDevice.Address);
                }
            }
        }

感谢您的帮助!

答案 2 :(得分:0)

问题解决了。我不需要蓝牙插座。我刚刚使用了覆盖方法&#34; KeyDown&#34;和&#34; KeyUp&#34;。现在效果很好:))

如果你需要一个套接字并且你有IOException: read failed, socket might closed这样的例外,那么你应该在这里阅读我的修复:

IOException: read failed, socket might closed - Bluetooth on Android 4.3