如何连接蓝牙设备? IOException异常

时间:2015-02-07 12:35:44

标签: android

我实施了以下BluetoothService,它来自官方 Android BluetoothChatService示例:

public class BluetoothService extends Thread {
    private static final String TAG = BluetoothService.class.getSimpleName();
    private static final String NAME_SECURE = TAG + "Secure";
    private static final String NAME_INSECURE = TAG + "Insecure";
    private static final UUID MY_UUID_SECURE = UUID.fromString("a6fb84f6-20b3-477f-9160-bcd028bddc99");
    private static final UUID MY_UUID_INSECURE = UUID.fromString("7dd8441a-1d4b-42f1-9996-a7d507548dfc");
    public static final int STATE_NONE = 0;  
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;
    private BluetoothAdapter bluetoothAdapter = null;
    private Handler handler = null;
    private AcceptThread secureAcceptThread = null;
    private AcceptThread insecureAcceptThread = null;
    private ConnectThread connectThread = null;
    private ConnectedThread connectedThread = null;
    private int bluetoothState = STATE_NONE;

    public BluetoothService(Handler handler) {
        this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        this.bluetoothState = STATE_NONE;
        this.handler = handler;
    }

    public synchronized void startConnection() {
        Log.d(TAG, "start");

        if (this.connectThread != null) {
            this.connectThread.cancel();
            this.connectThread = null;
        }

        if (this.connectedThread != null) {
            this.connectedThread.cancel();
            this.connectedThread = null;
        }

        this.setBluetoothState(STATE_LISTEN);

        if (this.secureAcceptThread == null) {
            this.secureAcceptThread = new AcceptThread(true);
            this.secureAcceptThread.start();
        }
        if (this.insecureAcceptThread == null) {
            this.insecureAcceptThread = new AcceptThread(false);
            this.insecureAcceptThread.start();
        }
    }

    public synchronized void connect(BluetoothDevice device, boolean secure) {
        if (this.bluetoothState == STATE_CONNECTING) {
            if (this.connectThread != null) {
                this.connectThread.cancel();
                this.connectThread = null;
            }
        }

        if (this.connectedThread != null) {
            this.connectedThread.cancel();
            this.connectedThread = null;
        }

        this.connectThread = new ConnectThread(device, secure);
        this.connectThread.start();

        this.setBluetoothState(STATE_CONNECTING);
    }

    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {
        if (this.connectThread != null) {
            this.connectThread.cancel();
            this.connectThread = null;
        }

        if (this.connectedThread != null) {
            this.connectedThread.cancel();
            this.connectedThread = null;
        }

        if (this.secureAcceptThread != null) {
            this.secureAcceptThread.cancel();
            this.secureAcceptThread = null;
        }

        if (this.insecureAcceptThread != null) {
            this.insecureAcceptThread.cancel();
            this.insecureAcceptThread = null;
        }

        this.connectedThread = new ConnectedThread(socket, socketType);
        this.connectedThread.start();

        Message msg = this.handler.obtainMessage(Globals.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();

        bundle.putString(Globals.DEVICE_NAME, device.getName());
        msg.setData(bundle);

        this.handler.sendMessage(msg);
        this.setBluetoothState(STATE_CONNECTED);
    }

    public synchronized void stopConnection() {
        if (this.connectThread != null) {
            this.connectThread.cancel();
            this.connectThread = null;
        }

        if (this.connectedThread != null) {
            this.connectedThread.cancel();
            this.connectedThread = null;
        }

        if (this.secureAcceptThread != null) {
            this.secureAcceptThread.cancel();
            this.secureAcceptThread = null;
        }

        if (this.insecureAcceptThread != null) {
            this.insecureAcceptThread.cancel();
            this.insecureAcceptThread = null;
        }

        this.setBluetoothState(STATE_NONE);
    }

    public void write(byte[] out) {
        ConnectedThread connectedThread = null;

        synchronized (this) {
            if (this.bluetoothState != STATE_CONNECTED) {
                return;
            }

            connectedThread = this.connectedThread;
        }

        connectedThread.write(out);
    }

    private void connectionFailed() {
        Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);

        Bundle bundle = new Bundle();
        bundle.putString(Globals.TOAST, "Unable to connect device");

        msg.setData(bundle);

        this.handler.sendMessage(msg);

        BluetoothService.this.start();
    }

    private void connectionLost() {
        Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);
        Bundle bundle = new Bundle();

        bundle.putString(Globals.TOAST, "Device connection was lost");
        msg.setData(bundle);

        this.handler.sendMessage(msg);

        BluetoothService.this.start();
    }

    public synchronized int getBluetoothState() {
        return this.bluetoothState;
    }

    private synchronized void setBluetoothState(int bluetoothState) {
        this.bluetoothState = bluetoothState;
    }

    private class AcceptThread extends Thread {
        private BluetoothServerSocket serverSocket = null;
        private String socketType = null;

        public AcceptThread(boolean secure) {
            BluetoothServerSocket tempServerSocket = null;

            this.socketType = secure ? "Secure" : "Insecure";

            try {
                if (secure) {
                    tempServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);
                } else {
                    tempServerSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + socketType + "listen() failed", e);
            }

            this.serverSocket = tempServerSocket;
        }

        public void run() {
            this.setName("AcceptThread" + socketType);

            BluetoothSocket socket = null;

            while (bluetoothState != STATE_CONNECTED) {
                try {
                    socket = this.serverSocket.accept();
                } catch (IOException e) {
                    break;
                }

                if (socket != null) {
                    synchronized (BluetoothService.this) {
                        switch (bluetoothState) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:
                            connected(socket, socket.getRemoteDevice(), socketType);
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
        }

        public void cancel() {
            try {
                this.serverSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + socketType + "close() of server failed", e);
            }
        }
    }

    private class ConnectThread extends Thread {
        private BluetoothSocket bluetoothSocket = null;
        private BluetoothDevice bluetoothDevice = null;
        private String socketType = null;

        public ConnectThread(BluetoothDevice bluetoothDevice, boolean secure) {
            this.bluetoothDevice = bluetoothDevice;
            this.socketType = secure ? "Secure" : "Insecure";

            BluetoothSocket tempBluetoothSocket = null;

            try {
                if (secure) {
                    tempBluetoothSocket = this.bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
                } else {
                    tempBluetoothSocket = this.bluetoothDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + this.socketType + "create() failed", e);
            }

            this.bluetoothSocket = tempBluetoothSocket;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread");

            this.setName("ConnectThread");

            bluetoothAdapter.cancelDiscovery();

            try {
                this.bluetoothSocket.connect();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);

                connectionFailed();

                try {
                    this.bluetoothSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() socket during connection failure", e2);
                }

                return;
            }

            synchronized (BluetoothService.this) {
                connectThread = null;
            }

            connected(this.bluetoothSocket, this.bluetoothDevice, this.socketType);
        }

        public void cancel() {
            try {
                this.bluetoothSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    private class ConnectedThread extends Thread {
        private BluetoothSocket bluetoothSocket = null;
        private InputStream inputStream = null;
        private OutputStream outputStream = null;

        public ConnectedThread(BluetoothSocket bluetoothSocket, String socketType) {
            Log.d(TAG, "create ConnectedThread");

            this.bluetoothSocket = bluetoothSocket;

            InputStream tempInputStream = null;
            OutputStream tempOutputStream = null;

            try {
                tempInputStream = this.bluetoothSocket.getInputStream();
                tempOutputStream = this.bluetoothSocket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            this.inputStream = tempInputStream;
            this.outputStream = tempOutputStream;
        }

        public void run() {
            byte[] buffer = new byte[1024];
            int bytes = 0;

            while (true) {
                try {
                    bytes = this.inputStream.read(buffer);

                    handler.obtainMessage(Globals.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);

                    connectionLost();

                    BluetoothService.this.start();

                    break;
                }
            }
        }

        public void write(byte[] buffer) {
            try {
                this.outputStream.write(buffer);

                handler.obtainMessage(Globals.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                this.bluetoothSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
}

当我现在想要使用以下代码连接到BluetoothDevice时:

private void connectDevice(Intent data, boolean secure) {
    String address = data.getExtras().getString(BluetoothFragment.EXTRA_DEVICE_ADDRESS);

    BluetoothDevice device = this.bluetoothAdapter.getRemoteDevice(address);

    this.bluetoothService.connect(device, secure);
}

我收到以下错误:

02-07 12:47:15.633: E/BluetoothService(17671): read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671): java.io.IOException: read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671):  at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:512)

所以我所做的一切都与android提供的例子完全一样。 您可以在Android中下载BluetoothChat的示例代码 工作室示例代码。

唯一令人好奇的是uuid。我不知道如何创建它们,如果使用特殊的uuid很重要。我刚刚使用了从Android Play商店下载的uuid生成器并执行了以下操作:

private static final UUID MY_UUID_SECURE = UUID.fromString("a6fb84f6-20b3-477f-9160-bcd028bddc99");
private static final UUID MY_UUID_INSECURE = UUID.fromString("7dd8441a-1d4b-42f1-9996-a7d507548dfc");

所以问题是:如何连接到BluetoothDevice

加成

我使用Nexus 7和Nexus 4以及最新的Android版本。 我下载了几个蓝牙连接应用程序和所有这些 应用程序无法在我的设备之间建立连接。所以 也许这不是代码的问题?它是Nexus还是Android 5.0.1错误?

1 个答案:

答案 0 :(得分:0)

你能试试这段代码吗?

您可以通过调用

将字符串传递给BT设备
BluetoothPrinterHelper.BT.send(context, data)

注意:代码假定您已连接并与BT设备配对,并且是配对列表中唯一的设备。您可以在 findDevice(BluetoothAdapter)方法中更改此行为。

此外,UUID可以通过调用UUID.randomUUID()。toString()在Java本身生成,但在这种情况下,UUID扮演不同的角色。这标识了目标BT设备正在运行的配置文件。您可以在此处查看更多相关信息BT-UUID

package com.example.bt;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.AsyncTask;

public enum class BluetoothPrinterHelper {
    BT;

    private BluetoothDevice device;
    private static BluetoothSocket socket;
    private BluetoothSocket tmp;
    private BluetoothAdapter adapter;
    private String deviceName;

    public void send(Context ctx, String data) {
        mTryConnect = new TryConnect();
        mTryConnect.execute();
        boolean isConnected = false;

        try {
            Log.d(TAG, "Establishing connection to device");
            isConnected = mTryConnect.get();
        } catch (InterruptedException e) {
            Log.e(TAG, "Error connecting to device");
            return;
        } catch (ExecutionException e) {
            Log.e(TAG, "Error connecting to device");
            return;
        }

        if (isConnected) {
            Log.d(TAG, "Connection to device successfully established");
            mTrySend = new TrySend(data);
            mTrySend.execute();
        } else {
            Toast.makeText(ctx, "No BT device connected", Toast.LENGTH_LONG).show();
        }
    }

    private BluetoothDevice findDevice(BluetoothAdapter adapter) {
        Log.d(TAG, "Finding BT devices");
        Set<BluetoothDevice> pairedDevices = null;

        try {
            pairedDevices = adapter.getBondedDevices();
        } catch (NullPointerException e) {
            Log.e(TAG, "Error retrieving paired devices");
        }

        if (pairedDevices != null && pairedDevices.size() == 1) {
            Log.d(TAG, "Found 1 paired device");
            for (BluetoothDevice bluetoothDevice : pairedDevices) {
                return bluetoothDevice;
            }
        } else {
            Log.w(TAG, "Many/No paired BT devices found");
        }
        return null;
    }

    private class TryConnect extends AsyncTask<Void, Void, Boolean> {
        public TryConnect() {
            adapter = BluetoothAdapter.getDefaultAdapter();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            // Check bonded devices list
            device = findDevice(adapter);

            if (adapter.isDiscovering()) {
                adapter.cancelDiscovery();
            }

            // Create a socket for the device connection
            if (device != null) {
                try {
                    deviceName = device.getName();
                    Log.d(TAG, "Creating socket");
                    tmp = device.createRfcommSocketToServiceRecord(DEVICE_UUID);
                } catch (NoSuchMethodException e) {
                    Log.e(TAG, "Printing - NoSuchMethodException", e);
                    return false;
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "Printing - IllegalArgumentException", e);
                    return false;
                } catch (IllegalAccessException e) {
                    Log.e(TAG, "Printing - IllegalAccessException", e);
                    return false;
                } catch (InvocationTargetException e) {
                    Log.e(TAG, "Printing - InvocationTargetException", e);
                    return false;
                }
            }
            socket = tmp;

            // Connect to the created socket and device
            try {
                Log.d(TAG, "Creating connection to: " + deviceName);
                socket.connect();
            } catch (IOException e) {
                Log.e(TAG, "Unable to connect. Closing connection", e);
                try {
                    socket.close();
                } catch (IOException e1) {
                    Log.e(TAG, "Unable to close connection during connection failure", e1);
                }
                return false;
            } catch (NullPointerException e) {
                Log.e(TAG, "NPE during BT socket connection");
            }
            return true;
        }
    }

    private class TrySend extends AsyncTask<Void, Void, Boolean> {
        byte[] out;

        public TrySend(String data) {
            try {
                out = data.getBytes("UTF-8");
            } catch (UnsupportedEncodingException e1) {
                Log.w(TAG, "UnsupportedEncodingException");
            }
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                // Get the output stream and ready for write
                try {
                    Log.d(TAG, "Creating output stream");
                    outStream = socket.getOutputStream();
                } catch (IOException e) {
                    Log.e(TAG, "Socket not created", e);
                    return false;
                } catch (NullPointerException e) {
                    Log.e(TAG, "NPE retreiving socket stream");
                    return false;
                }

                // Write data to the socket for printing
                try {
                    Log.d(TAG, "Write to output stream");

                    // Write format
                    outStream.write(command);

                    // Write data to print
                    DataOutputStream dataOutputStream = new DataOutputStream(outStream);
                    dataOutputStream.write(out);

                    dataOutputStream.flush();
                } catch (IOException e) {
                    Log.e(TAG, "Exception during BT write to device", e);
                    return false;
                } catch (NullPointerException e) {
                    Log.e(TAG, "NPE during socket write");
                } finally {
                    try {
                        outStream.close();
                    } catch (IOException e) {
                        Log.e(TAG, "Exception during closing outstream", e);
                    } catch (NullPointerException e) {
                        Log.e(TAG, "NPE during BT socket close");
                    }
                }

                // Close the socket and cleanup
                try {
                    Log.d(TAG, "Closing socket");
                    socket.close();
                } catch (IOException e) {
                    Log.e(TAG, "Socket closing exception", e);
                    return false;
                } catch (NullPointerException e) {
                    Log.e(TAG, "NPE during BT socket close");
                }
            } finally {
                adapter = null;
                device = null;
                socket = null;
                outStream = null;
            }

            return true;
        }
    }
}


更新:您可以尝试以下代码:

Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
tmp = (BluetoothSocket) m.invoke(device, 1);

而不是

tmp = device.createRfcommSocketToServiceRecord(DEVICE_UUID);