BluetoothSocket not connecting to target device

2019-02-21 03:55发布

问题:

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

read failed, socket might closed or timeout, read ret: -1

Just to illustrate how my app works, I have a RecyclerView populated with the devices my Bluetooth scan has found, then when I click an item the app is supposed to connect with that device.

Below is my the code for my connection thread:

private val MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")

private lateinit var device: BluetoothDevice
private lateinit var onDeviceActionListener: OnDeviceActionListener
private lateinit var socket: BluetoothSocket

fun init(device: BluetoothDevice,
         onDeviceActionListener: OnDeviceActionListener): ConnectionThread {
    this.device = device
    this.onDeviceActionListener = onDeviceActionListener
    try {
        socket = device.createRfcommSocketToServiceRecord(MY_UUID)
    } catch (e: IOException) {
        Log.e(TAG, "Error creating socket", e)
    }
    return this
}

override fun run() {
    try {
        socket.connect()
    } catch (openException: IOException) {
        Log.e(TAG, "Error opening connection. Trying to close...", openException)
        try {
            socket.close()
        } catch (closeException: IOException) {
            Log.e(TAG, "Error closing socket", closeException)
        }
        return
    }
    onDeviceActionListener.onDeviceConnect(device)
}

My guess is there is something wrong with my UUID. I've tried some other values but still didn't work.

Any help will be much appreciated.

回答1:

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<KeyValueModel> getPairedDevices(){
    return getPairedDevices(BluetoothAdapter.getDefaultAdapter());
}
public ArrayList<KeyValueModel> getPairedDevices(BluetoothAdapter adapter){
    ArrayList<KeyValueModel> bondedDevices = new ArrayList<KeyValueModel>();

    Set<BluetoothDevice> 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:

 <receiver
        android:name=".receivers.BluetoothChangedReceiver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
            <action android:name="android.bluetooth.adapter.action.SCAN_MODE_CHANGED" />
            <action android:name="android.bluetooth.adapter.action.DISCOVERY_STARTED" />
            <action android:name="android.bluetooth.adapter.action.DISCOVERY_FINISHED" />
            <action android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
            <action android:name="android.bluetooth.device.action.FOUND" />
            <action android:name="android.bluetooth.device.action.DISAPPEARED" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.BluetoothDeviceReceiver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="android.bluetooth.device.action.FOUND" />
            <action android:name="android.bluetooth.device.action.DISAPPEARED" />
            <action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
            <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
            <action android:name="android.bluetooth.device.action.ACTION_ACL_DISCONNECT_REQUESTED" />
            <action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
            <action android:name="android.bluetooth.device.action.UUID" />
        </intent-filter>
    </receiver>