BluetoothSocket not connecting to target device

后端 未结 1 1998
自闭症患者
自闭症患者 2021-01-17 04:15

I\'m trying to connect my device to another one via Bluetooth, but when I select the device I want to connect with, I get an IOException saying

1条回答
  •  时光说笑
    2021-01-17 04:47

    Well, I don't see exactly what you are doing wrong here. However, I have done quite a bit of Bluetooth work. More recently just focused in BLE. You should be able to discover your nearby BT devices and see their UUIDs.

    I have written a helper class about 3 years ago so it's a little old, but should be mostly the same code. Happy to share it with you if it helps.

    public class BluetoothConnector {
    
    private static final String TAG = Globals.SEARCH_STRING + BluetoothConnector.class.getSimpleName();
    private static final String DEFAULT_SERVER_NAME_FOR_APP = "tn_bt_default_server";
    private static final int DEFAULT_DISCOVERABLE_DURATION_MS = 30000;
    private static final UUID DEFAULT_UUID = UUID.fromString("6534c201-039c-4e4f-89f9-5ca8cfeb9667");
    public static final int ENABLE_DISCOVER_INTENT = 1002;
    
    protected boolean mIsToastEnabled = false; //Access from calling class to enable toasting of progress to screen if necessary
    private Handler mUIHandler;
    private static ServerSocketThread mServerSocketThread;
    private static ClientSocketThread mClientSocketThread;
    private ManageConnectionThread mManageConnectionThread;
    private Context mContext;
    private IBluetoothDataListener mBluetoothDataListener;
    public final Object ServerSocketLock = new Object();
    public final Object ClientSocketLock = new Object();
    public final Object ManageConnectionLock = new Object();
    
    
    
    public BluetoothConnector(Context context, IBluetoothDataListener listener){
        this(context, new Handler(Looper.getMainLooper()), listener);
    
    }
    public BluetoothConnector(Context context, Handler UIHandler, IBluetoothDataListener listener){
        Log.v(TAG, "BluetoothConnector(context=" + context + ", Handler=" + UIHandler.getClass().getSimpleName() + ", IBluetoothDataListener=" + listener.getClass().getSimpleName());
        mContext = context;
        mUIHandler = UIHandler;
        mBluetoothDataListener = listener;
    
    }
    
    
    public void makeThisDeviceDiscoverable(Activity callingActivity){
        makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), DEFAULT_DISCOVERABLE_DURATION_MS);
    
    }
    public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter){
        makeThisDeviceDiscoverable(callingActivity, adapter, DEFAULT_DISCOVERABLE_DURATION_MS);
    
    }
    public void makeThisDeviceDiscoverable(Activity callingActivity, int durationInMs){
        makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), durationInMs);
    
    }
    public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter, int durationInMs) {
        Log.v(TAG, "makeThisDeviceDiscoverable(callingActivity=" + callingActivity.getClass().getSimpleName() + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()) + ", duration=" + String.valueOf(durationInMs));
        if(adapter == null){
            Log.v(TAG, "adapter is null");
    
        }else if(adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Log.v(TAG, "Launching Activity to request Discoverable Permission");
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, durationInMs);
            callingActivity.startActivityForResult(discoverableIntent, ENABLE_DISCOVER_INTENT);
    
        }else{
            Log.v(TAG, "adapter is already in SCAN MODE");
    
        }
    
    }
    public void awaitConnectionFromDevice(){
        awaitConnectionFromDevice(DEFAULT_UUID, BluetoothAdapter.getDefaultAdapter());
    
    }
    public void awaitConnectionFromDevice(UUID commonKey){
        awaitConnectionFromDevice(commonKey, BluetoothAdapter.getDefaultAdapter());
    
    }
    public void awaitConnectionFromDevice(BluetoothAdapter adapter){
        awaitConnectionFromDevice(DEFAULT_UUID, adapter);
    
    }
    public void awaitConnectionFromDevice(UUID commonKey, BluetoothAdapter adapter){
        Log.v(TAG, "awaitConnectionFromDevice for UUID: " + String.valueOf(commonKey) + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
        cancelDiscovery();
    
        synchronized (ServerSocketLock){
            if(mServerSocketThread != null){
                Log.v(TAG, "Server Socket Thread was not null so canceling current Thread");
                mServerSocketThread.cancel();
    
            }
    
            Log.v(TAG, "Attempting to Start new ServerThread");
            mServerSocketThread = new ServerSocketThread(commonKey, adapter);
            mServerSocketThread.start();
    
        }
    
    }
    public void cancelAwaitingConnectionFromDevice(){
        Log.v(TAG, "cancelAwaitingConnectionFromDevice");
        synchronized (ServerSocketLock){
            if(mServerSocketThread != null){
                mServerSocketThread.cancel();
                mServerSocketThread = null;
                Log.v(TAG, "canceling Server Socket Thread");
    
            }else{
                Log.v(TAG, "Server Socket null, so not canceling");
    
            }
    
        }
    
    }
    
    public void startDiscovery() {
        startDiscovery(BluetoothAdapter.getDefaultAdapter());
    
    }
    public void startDiscovery(BluetoothAdapter adapter){
        Log.v(TAG, "startDiscovery to find list of devices in range");
        adapter.startDiscovery();
    
    }
    public void cancelDiscovery() {
        cancelDiscovery(BluetoothAdapter.getDefaultAdapter());
    
    }
    public void cancelDiscovery(BluetoothAdapter adapter){
        Log.v(TAG, "cancelDiscovery");
        adapter.cancelDiscovery();
    
    }
    public void connectToDevice(BluetoothDevice device){
        connectToDevice(device, DEFAULT_UUID);
    
    }
    public void connectToDevice(BluetoothDevice device, UUID commonKey){
        Log.v(TAG, "connectToDevice(BluetoothDevice=" + (device == null ? "null" : device.getName()) + ", UUID=" + String.valueOf(commonKey));
        synchronized (ClientSocketLock){
            if(mClientSocketThread != null){
                Log.v(TAG, "Client Socket Thread was not null so canceling current Thread");
                mClientSocketThread.cancel();
    
            }else{
                Log.v(TAG, "Client Socket Thread is NULL so not canceling");
    
            }
    
            Log.v(TAG, "ClientSocketThread Starting");
            mClientSocketThread = new ClientSocketThread(device, commonKey);
            mClientSocketThread.start();
    
        }
    
    }
    public BluetoothDevice getBluetoothDeviceByMac(String mac){
        Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac);
        return getBluetoothDeviceByMac(mac, BluetoothAdapter.getDefaultAdapter());
    
    }
    public BluetoothDevice getBluetoothDeviceByMac(String mac, BluetoothAdapter adapter) {
        Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
        return adapter.getRemoteDevice(mac);
    
    }
    
    public ArrayList getPairedDevices(){
        return getPairedDevices(BluetoothAdapter.getDefaultAdapter());
    }
    public ArrayList getPairedDevices(BluetoothAdapter adapter){
        ArrayList bondedDevices = new ArrayList();
    
        Set pairedDevices = adapter.getBondedDevices();
        Log.v(TAG, "getPairedDevices Found " + pairedDevices.size() + " number of paired devices");
    
        // If there are paired devices
        if (pairedDevices.size() > 0) {
            // Loop through paired devices
            for (BluetoothDevice device : pairedDevices) {
                // Add the name and address to an array adapter to show in a ListView
                bondedDevices.add(new KeyValueModel(device.getAddress(), device.getName()));
    
            }
        }
    
        return bondedDevices;
    }
    public static void unpairDevice(BluetoothDevice device){
        Log.v(TAG, "unpairDevice");
        try{
            Method method = device.getClass().getMethod("removeBond", (Class[]) null);
            method.invoke(device, (Object[]) null);
    
        }catch (Exception ex){
            Log.e(TAG, "Error Unpairing Device: " + ex.getMessage());
    
        }
    }
    public boolean sendDataToConnectedDevice(byte[] data){
        Log.v(TAG, "sendDataToConnectedDevice");
        synchronized (ManageConnectionLock){
            mManageConnectionThread.write(data);
            return true;
    
        }
    
    }
    public void setBluetoothDataListener(IBluetoothDataListener listener){
        mBluetoothDataListener = listener;
    }
    public boolean getIsConnected(){
        synchronized (ManageConnectionLock) {
            return mManageConnectionThread != null && mManageConnectionThread.isAlive();
    
        }
    }
    
    private void startManageConnectionThread(BluetoothSocket socket){
        Log.v(TAG, "startManageConnectionThread for Socket: " + (socket == null ? "null" : socket.getClass().getSimpleName()));
        synchronized (ManageConnectionLock) {
            mManageConnectionThread = new ManageConnectionThread(socket);
            mManageConnectionThread.start();
    
        }
    
    }
    private void handleDataReceivedFromConnectedDevice(final byte[] bytes){
        Log.v(TAG, "handleDataReceivedFromConnectedDevice");
        Log.v(TAG, "bytes to Listener: " + new String(bytes));
    
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mBluetoothDataListener != null) {
                        mBluetoothDataListener.onReceivedPayloadFromConnectedDevice(bytes);
    
                    }
    
                }
    
            });
    
        }else{
            Log.v(TAG, "UIHandler was null so skipped sending payload to listener");
    
        }
    
    }
    private void handleConnected(){
        Log.e(TAG, "handleConnected");
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onConnectedToTargetDevice();
    
                    }
    
                }
    
            });
    
        }else{
            Log.v(TAG, "UIHandler was null so skipped sending payload to listener");
    
        }
    
    }
    private void handleDisconnected(){
        Log.e(TAG, "handleDisconnected");
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onDisconnectedFromTargetDevice();
    
                    }
                }
            });
    
        }else{
            Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
    
        }
    }
    private void handleFailedToConnectAsServer(final Exception ex){
        Log.e(TAG, "handleFailedToConnectAsServer ex:  " + ex.getMessage());
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onFailedToReceiveConnectionFromTargetDevice(ex);
    
                    }
                }
            });
    
        }else{
            Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
    
        }
    
    }
    private void handleFailedToConnectAsClient(final Exception ex){
        Log.e(TAG, "handleFailedToConnectAsClient ex:  " + ex.getMessage());
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onFailedToConnectToTargetDevice(ex);
    
                    }
                }
            });
    
        }else{
            Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
    
        }
    }
    private void handleErrorInRetrievingData(final Exception ex){
        Log.e(TAG, "handleErrorInRetrievingData ex:  " + ex.getMessage());
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onErrorReceivingPayloadFromConnectedDevice(ex);
    
                    }
    
                }
            });
    
        }else{
            Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
    
        }
    
    }
    private void handleFailedToSendDataToConnectedDevice(final Exception ex){
        Log.e(TAG, "handleFailedToSendDataToConnectedDevice ex:  " + ex.getMessage());
        if(mUIHandler != null && mBluetoothDataListener != null){
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mBluetoothDataListener != null){
                        mBluetoothDataListener.onFailedToSendDataToConnectedDevice(ex);
    
                    }
    
                }
            });
    
        }else{
            Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
    
        }
    
    }
    private void toastMessage(final String value){
        if(!mIsToastEnabled || mUIHandler == null) {
            return;
        }
    
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                try{
                    Toast.makeText(mContext, value, Toast.LENGTH_SHORT).show();
    
                }catch(Exception ex){
                    Log.v(TAG, "Error Toasting, possibly bad handler, or context: " + ex.getMessage());
    
                }
            }
        });
    }
    
    
    private class ServerSocketThread extends Thread{
    
        private final String TAG = Globals.SEARCH_STRING + ServerSocketThread.class.getSimpleName();
        private final BluetoothServerSocket mServerSocket;
    
        public ServerSocketThread(UUID commonKey, BluetoothAdapter adapter) {
            Log.v(TAG, "ServerSocketThread Constructor");
            BluetoothServerSocket tmp = null;
    
            try {
                Log.v(TAG, "listening for RFComas Server: " + DEFAULT_SERVER_NAME_FOR_APP + ", and commonKey: " + String.valueOf(commonKey));
                // MY_UUID is the app's UUID string, also used by the client code
                tmp = adapter.listenUsingRfcommWithServiceRecord(DEFAULT_SERVER_NAME_FOR_APP, commonKey);
                toastMessage("Listening for RFComm As Server on UUID: " + String.valueOf(commonKey));
    
            } catch (IOException e) {
                Log.e(TAG, "Error creating ServerSocket: " + e.getMessage());
                toastMessage("Error Creating ServerSocket: " + e.getMessage());
    
            }
    
            mServerSocket = tmp;
    
        }
    
        public void run() {
            Log.v(TAG, "ServerSocket run");
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (mServerSocket != null) {
                try {
                    Log.v(TAG, "ServerSocket.accept()");
                    toastMessage("ServerSocket.accept()");
                    //Waits for Client Connection to pass Socket, then we close down
                    socket = mServerSocket.accept();
    
                } catch (IOException e) {
                    Log.e(TAG, "ServerSocket.accept() Error: " + e.getMessage());
                    toastMessage("ServerSocket.accept() Error: " + e.getMessage());
                    handleFailedToConnectAsServer(e);
                    break;
    
                }
    
                // If a connection was accepted we don't need to keep server listening, so close unless multiple client/server connections is desired
                if (socket != null) {
                    try{
                        Log.v(TAG, "ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
                        toastMessage("ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
                        // Do work to manage the connection (in a separate thread)
                        startManageConnectionThread(socket);
                        //mServerSocket.close();
    
                    }catch(Exception ex){
                        Log.e(TAG, "Exception closing Server Socket");
    
                    }
    
                    //break; //Add in Break if you want to shut down listening for connections
                }else{
                    Log.v(TAG, "Socket wasn't accepted");
                    toastMessage("Socket wasn't accepted");
                    handleFailedToConnectAsServer(new Exception("Socket is Null"));
    
                }
            }
    
            Log.v(TAG, "Exiting Server Accept Thread");
        }
        public void cancel() {
            try {
                Log.v(TAG, "ServerSocketThread Canceled");
                mServerSocket.close();
    
            } catch (IOException e) {
                Log.e(TAG, "ServerSocketThread Error: " + e.getMessage());
    
            }
        }
    
    }
    private class ClientSocketThread extends Thread{
    
        private BluetoothSocket mSocket;
        private final BluetoothDevice mDevice;
    
        public ClientSocketThread(BluetoothDevice device, UUID commonKey) {
            Log.v(TAG, "ClientSocketThread Constructor");
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mDevice = device;
    
            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                Log.v(TAG, "Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
                toastMessage("Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(commonKey);
    
            } catch (IOException e) {
                Log.e(TAG, "Error creating Client Socket: " + e.getMessage());
                toastMessage("Creating Socket Exception: " + e.getMessage());
                handleFailedToConnectAsClient(e);
    
            }
    
            mSocket = tmp;
    
        }
    
        public void run() {
            try {
                if(mSocket == null){
                    Log.e(TAG, "Error Client Socket is Null, Canceling Client Thread");
                    return;
    
                }
    
                Log.v(TAG, "Client Connecting");
                // Connect to the server, or timeout eventually
                toastMessage("Client Connecting");
                mSocket.connect();
    
            } catch (IOException connectException) {
                // Unable to connect; close the socket and try the fallback method of reflection with port to connect
                try {
                    Log.e("", "trying fallback...");
                    toastMessage("Client Connection Failed Exception: " + connectException.getMessage());
    
                    mSocket = (BluetoothSocket) mDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mDevice, 1);
                    toastMessage("Client Connect Again Attempt 2, but with fall back Reflection and port");
                    Log.v(TAG, "Client Connect Again Attempt 2, but with fall back Reflection and port");
                    mSocket.connect();
    
                    Log.e("", "Connected");
                    toastMessage("Client Connected");
    
                } catch (Exception ex) {
                    Log.e("", "Couldn't establish Bluetooth connection!");
                    toastMessage("Client Couldn't Establish Connection to Server: " + ex.getMessage());
                    handleFailedToConnectAsClient(ex);
                    return;
    
                }
            }
    
            // Do work to manage the connection (in a separate thread)
            startManageConnectionThread(mSocket);
        }
        public void cancel() {
            try {
                Log.v(TAG, "Client Socket cancel");
                mSocket.close();
    
            } catch (IOException e) {
                Log.e(TAG, "Error Closing Socket");
    
            }
        }
    
    }
    private class ManageConnectionThread extends Thread {
    
        /////////////
        // MEMBERS //
        /////////////
        private final String TAG = Globals.SEARCH_STRING + ManageConnectionThread.class.getSimpleName();
        private final BluetoothSocket mSocket;
        private final InputStream mInStream;
        private final OutputStream mOutStream;
    
    
        //////////////////
        //  CONSTRUCTOR //
        //////////////////
        public ManageConnectionThread(BluetoothSocket socket) {
            mSocket = socket;
    
            handleConnected();
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
    
            // Get the input and output streams, using temp objects because
            try {
                Log.v(TAG, "ManageConnectionThread Constructor");
                Log.v(TAG, "Connected to Socket = " + String.valueOf(socket.isConnected()));
                toastMessage("Listening for input or output Stream");
                Log.v(TAG, "Get InputStream");
                tmpIn = socket.getInputStream();
                Log.v(TAG, "Get OutputStream");
                tmpOut = socket.getOutputStream();
    
            } catch (IOException e) {
                Log.e(TAG, "Error getting Socket Streams: " + e.getMessage());
                toastMessage("Connect Thread: Error: " + e.getMessage());
                handleErrorInRetrievingData(e);
    
            }
    
            mInStream = tmpIn;
            mOutStream = tmpOut;
        }
    
    
        ///////////////
        // OVERRIDES //
        ///////////////
        public void run() {
            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    byte[] data = new byte[16384];
                    int nRead;
                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    
                    while ((nRead = mInStream.read(data, 0, data.length)) != -1) {
                        //Log.v(TAG, "bytes Read: " + String.valueOf(nRead));
                        buffer.write(data, 0, nRead);
    
                        //TODO Find better way to find End Of Message rather than looking for }
                        String temp = new String(buffer.toByteArray());
                        //Log.v(TAG, "current Data: " + temp);
                        if(temp.contains("}")){
                            Log.v(TAG, "bytes reading complete");
                            handleDataReceivedFromConnectedDevice(buffer.toByteArray());
                            buffer.flush();
                            buffer = new ByteArrayOutputStream();
    
                        }else{
                            Log.v(TAG, "More bytes Available");
    
                        }
    
                    }
    
                } catch (IOException e) {
                    Log.e(TAG, "Error reading inputStream");
                    handleErrorInRetrievingData(e);
                    break;
    
                }
    
            }
    
            Log.v(TAG, "Exiting Managed Connection Thread");
            handleDisconnected();
    
        }
    
    
        /////////////
        // METHODS //
        /////////////
        public void write(byte[] bytes) {
            try {
                Log.v(TAG, "ManageConnectionThread write(bytes)");
                mOutStream.write(bytes);
    
            } catch (IOException e) {
                Log.e(TAG, "Error Writing Stream: " + e.getMessage());
                handleFailedToSendDataToConnectedDevice(e);
    
            }
        }
        public void cancel() {
            try {
                Log.v(TAG, "ManageConnectionThread cancel");
                handleDisconnected();
                mSocket.close();
    
            } catch (IOException e) {
                Log.e(TAG, "Error Closing BluetoothSocket: " + e.getMessage());
    
            }
        }
    
    }
    
    
    public interface IBluetoothDataListener{
    
        //////////////////////
        // OVERRIDE METHODS //
        //////////////////////
        void onReceivedPayloadFromConnectedDevice(byte[] payload);
        void onErrorReceivingPayloadFromConnectedDevice(Exception ex);
        void onFailedToConnectToTargetDevice(Exception ex);
        void onFailedToReceiveConnectionFromTargetDevice(Exception ex);
        void onFailedToSendDataToConnectedDevice(Exception ex);
        void onConnectedToTargetDevice();
        void onDisconnectedFromTargetDevice();
    
    }
    

    }

    Then of course you will want to make sure you have your broadcast receivers setup:

     
            
                
                
                
                
                
                
                
            
        
    
        
            
                
                
                
                
                
                
                
            
        
    

    0 讨论(0)
提交回复
热议问题