android bluetooth: Bluetooth's Opening, Searching, Matching and Connecting

Keywords: socket Android Mac Attribute

Android blt only supports API 18 Android 4.3 or more, and some functions even require API 19 Android 4.4.
So before we do blt projects, we must be clear about the range of versions available.

I'm going to talk about the operation of opening the BLT gate. These operations are how to open blt, how to search for other devices, how to pair the selected devices, how to connect the previously paired devices through the mac address, and how to communicate between two (or more) devices connected successfully.

Before learning about blt, it is important to understand how BLT enables communication between two devices. Let's first look at the basic steps:

1. Open blt.
—— 1) Authority
—— 2) whether the monitoring device opens blt
—— 3) Operate, open or close blt

2. Search for nearby devices
—— 1) Make the device can be searched nearby for up to 300 seconds; (With the gradual upgrading of the api, it may be more than 300 seconds, and do some optimization processing.)
—— 2) Search for connected devices nearby; outdated APIs call back search results in the interface, while new APIs require broadcasting to receive search results. (We use broadcasting to receive results here)

3. Matching with the target device
—— 1) For the target device pairing, the android system itself will complete the matching action and save the mac address of the device that has been successfully matched for the next automatic matching.
—— 2) Automatic matching of paired equipment. This action is also done by the system. We just need to judge whether the system has been paired or not according to the state it gives us.

4. Connect with the successfully matched device
—— 1) If you want to connect successfully paired devices, you must first establish the server side. The server establishes a connection that only threads block waiting for the client.
—— 2) Ensure that the client is established after the server is established. The client's connection process is also thread-blocked. When the server receives a message after the connection is successful, it indicates that the paired device has been successfully connected.

5. Notes:
—— 1) Matched successful devices do not need to be paired again, only need to get the mac address from the system to connect. This is judged by the state value returned by the system.
—— 2) Searching for nearby devices is a memory-consuming activity. We must stop searching before connecting devices.
—— 3) Successful matching of equipment does not mean successful connection. Matching and joining are two different things, and matching is before joining action.
—— 4) When our program clearly states that "no blt operation is needed", we should register blt broadcasting in time, stop blt connection and cancel Bluetooth objects. And this operation such as: program exit, user no operation timeout, logic does not need blt connection.

These are the steps to transmit information normally after a successful Bluetooth connection.
Next, let's look at the representation of the corresponding steps in the code logic.

1. Permission.

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  • 1
  • 2
  • 1
  • 2

2. Obtain Bluetooth management object. The main function of Bluetooth Manager is to get the objects we need from it.

//@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
//First get Bluetooth Manager
 BluetoothManager bluetoothManager=(BluetoothManager) context.getService(Context.BLUETOOTH_SERVICE);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

3. Get Bluetooth adapter. Bluetooth adapter is the main object for us to operate Bluetooth. We can get paired Bluetooth sets, Bluetooth transmission objects and so on.

//Get Bluetooth Adapter
if (bluetoothManager != null)
    BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

3. Register broadcasting to receive Bluetooth matching information. Call before Bluetooth is turned on

// Use Broadcast Receiver to Retrieve Search Results
        IntentFilter intent = new IntentFilter();
        intent.addAction(BluetoothDevice.ACTION_FOUND);//Search Discovery Device
        intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//State change
        intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//Action Scanning Mode Changed
        intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//The state of action has changed.
        context.registerReceiver(searchDevices, intent);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
 /**
     * Bluetooth Receives Broadcasting
     */
    private BroadcastReceiver searchDevices = new BroadcastReceiver() {
        //Receive
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Bundle b = intent.getExtras();
            Object[] lstName = b.keySet().toArray();

            // Display all received messages and their details
            for (int i = 0; i < lstName.length; i++) {
                String keyName = lstName[i].toString();
                Log.e("bluetooth", keyName + ">>>" + String.valueOf(b.get(keyName)));
            }
            BluetoothDevice device;
            // When searching for a device, get information about the device; note that it is possible to search for the same device repeatedly.
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                onRegisterBltReceiver.onBluetoothDevice(device);
            }
            //When the state changes
            else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING://Pairing
                        Log.d("BlueToothTestActivity", "Pairing......");
                        onRegisterBltReceiver.onBltIng(device);
                        break;
                    case BluetoothDevice.BOND_BONDED://End of pairing
                        Log.d("BlueToothTestActivity", "Finish pairing");
                        onRegisterBltReceiver.onBltEnd(device);
                        break;
                    case BluetoothDevice.BOND_NONE://Unpairing/Unpairing
                        Log.d("BlueToothTestActivity", "Cancel pairing");
                        onRegisterBltReceiver.onBltNone(device);
                    default:
                        break;
                }
            }
        }
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

4. Anti-registered broadcast and clear Bluetooth connection. Called when Bluetooth is not required

/**
     * Anti-Registered Broadcasting Cancels Bluetooth Matching
     *
     * @param context
     */
    public void unregisterReceiver(Context context) {
        context.unregisterReceiver(searchDevices);
        if (mBluetoothAdapter != null)
            mBluetoothAdapter.cancelDiscovery();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5. Determine whether the current device supports Bluetooth or not, and if so, turn on Bluetooth

   /**
     * Determine if Bluetooth is supported and turn on Bluetooth
     * Once you get the Bluetooth Adapter, you also need to determine whether Bluetooth is supported or not, and whether Bluetooth is turned on.
     * If not, you need to let the user open Bluetooth:
     */
    public void checkBleDevice(Context context) {
        if (mBluetoothAdapter != null) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(enableBtIntent);
            }
        } else {
            Log.i("blueTooth", "Bluetooth is not supported on this phone");
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

6. Search Bluetooth. After searching, it is added to a custom collection for the logical use of its own program. Note: The search results will be called back in the broadcast, there is no callback. If an outdated interface is used, the result is called back in the current logic. We use broadcasting here. We don't recommend outdated methods.

/**
     * Search for Bluetooth Devices
     * Search for BLE devices by calling Bluetooth Adapter's startLeScan().
     * Calling this method requires passing in the BluetoothAdapter.LeScanCallback parameter.
     * So you need to implement the Bluetooth Adapter. LeScanCallback interface, through which the search results of BLE devices will be returned.
     * <p/>
     * Since searching requires minimizing power consumption, attention should be paid to the following in practical use:
     * 1,When the corresponding device is found, the scanning is stopped immediately.
     * 2,Do not cycle the search device, set the appropriate time limit for each search. Avoid continuous scanning and power consumption when the equipment is not available.
     * <p/>
     * If you only need to search for the specified UUID peripherals, you can call the startLeScan(UUID[], BluetoothAdapter.LeScanCallback) method.
     * The UUID array specifies the UUID of GATT Services supported by your application.
     * <p/>
     * Note: When searching, you can only search for traditional Bluetooth devices or BLE devices, which are completely independent and cannot be searched at the same time.
     */
    private boolean startSearthBltDevice(Context context) {
        //Start searching for devices. When a device is searched, it should be added to the device collection and saved.
        checkBleDevice(context);
        //If a new device is currently found, stop scanning and the new device currently scanned will be broadcasted to the new logic.
        if (getmBluetoothAdapter().isDiscovering())
            stopSearthBltDevice();
        Log.i("bluetooth", "Bluetooth address:" + getmBluetoothAdapter().getAddress());
        //Start search
        mBluetoothAdapter.startDiscovery();
        //true here does not mean that the device has been searched, but that the search has started successfully.
        return true;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

7. Stop searching for Bluetooth devices

public boolean stopSearthBltDevice() {
        //Suspend Search Device
        if(mBluetoothAdapter!=null)
        return mBluetoothAdapter.cancelDiscovery();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

8. Connect Bluetooth. Note: The premise of connecting Bluetooth is that we have established the Bluetooth server. So, let's build a Bluetooth server first.
—— 1) Set up Bluetooth server first

/**
     * This operation should be placed in a sub-thread because there is a thread blocking problem
     */
    public void run(Handler handler) {
        //Server-side bltsocket s need to pass in uuid and a stand-alone string for validation, usually in the form of a package name
        BluetoothServerSocket  bluetoothServerSocket = tmBluetoothAdapter.listenUsingRfcommWithServiceRecord("com.bluetooth.demo", BltContant.SPP_UUID);
        while (true) {
            try {
                //Note that when accept() returns to Bluetooth Socket, the socket is connected, so the connect method should not be called.
                //Threads are blocked here and will not go down until a Bluetooth device is linked in.
                socket = getBluetoothServerSocket().accept();
                if (socket != null) {
                    BltAppliaction.bluetoothSocket = socket;
                    //Callback result notification
                    Message message = new Message();
                    message.what = 3;
                    message.obj = socket.getRemoteDevice();
                    handler.sendMessage(message);
                    //If your Bluetooth device is a one-to-one connection, execute the following code
                    getBluetoothServerSocket().close();
                    //If your Bluetooth device is one-to-many, you should call break; jump out of the loop
                    //break;
                }
            } catch (IOException e) {
                try {
                    getBluetoothServerSocket().close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                break;
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

—— 2) After the Bluetooth server is established, the operation of connecting Bluetooth is carried out.

 /**
     * Attempt to connect to a device, done in a sub-thread, because the thread will block
     *
     * @param btDev Bluetooth Device Object
     * @param handler Result callback event
     * @return
     */
    private void connect(BluetoothDevice btDev, Handler handler) {
        try {
            //Connecting via a uuid negotiated with the server
            mBluetoothSocket = btDev.createRfcommSocketToServiceRecord(BltContant.SPP_UUID);
            if (mBluetoothSocket != null)
                //There is only one bluetooth globally, so we can save this socket object in application
                BltAppliaction.bluetoothSocket = mBluetoothSocket;
            //The bltSocket object is obtained by reflection, which is the same as the result of uuid connection, but the reflection method is not advocated here.
            //mBluetoothSocket = (BluetoothSocket) btDev.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(btDev, 1);
            Log.d("blueTooth", "Start connecting...");
            //Called before establishment
            if (getmBluetoothAdapter().isDiscovering())
                //stop searching
                getmBluetoothAdapter().cancelDiscovery();
            //Call the connection if the current socket is disconnected
            if (!getmBluetoothSocket().isConnected()) {
                //You should make sure that the device does not perform the search operation when connecting () is called.
                // If the search device is also running at the same time, the connection rate will be significantly reduced and the connection will fail to a large extent.
                getmBluetoothSocket().connect();
            }
            Log.d("blueTooth", "have already been linked");
            if (handler == null) return;
            //Result callback
            Message message = new Message();
            message.what = 4;
            message.obj = btDev;
            handler.sendMessage(message);
        } catch (Exception e) {
            Log.e("blueTooth", "...link failure");
            try {
                getmBluetoothSocket().close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

9. Automatically connect the previously matched successful equipment. Note: The premise of the connection is that the server side has been opened, and if not, the 8.1 operation will be performed.

/**
     * Trying to pair and connect
     *
     * @param btDev
     */
    public void createBond(BluetoothDevice btDev, Handler handler) {
        if (btDev.getBondState() == BluetoothDevice.BOND_NONE) {
            //If the device cancels the pairing, try pairing
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                btDev.createBond();
            }
        } else if (btDev.getBondState() == BluetoothDevice.BOND_BONDED) {
            //If the device has been paired, try to connect
            connect(btDev, handler);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
 /**
     * Get a pair of successful devices saved by the system and try to connect them
     */
    public void getBltList() {
        if (getmBluetoothAdapter() == null) return;
        //Get the set of paired remote Bluetooth devices
        Set<BluetoothDevice> devices = getmBluetoothAdapter().getBondedDevices();
        if (devices.size() > 0) {
            for (Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext(); ) {
                BluetoothDevice device = it.next();
                //Automatically connect existing Bluetooth devices
                createBond(device, null);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Note: The outside world only needs to call getBltList(); the method can be automatically connected.

10. Input mac address to connect device automatically. The premise is that the system was originally connected to the address.

 /**
     * Input mac address for automatic matching
     * The premise is that the system saves the object of the address.
     *
     * @param address
     */
    public void autoConnect(String address, Handler handler) {
        if (getmBluetoothAdapter().isDiscovering()) getmBluetoothAdapter().cancelDiscovery();
        BluetoothDevice btDev = getmBluetoothAdapter().getRemoteDevice(address);
        connect(btDev, handler);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

11. Bluetooth connection status. Used to determine whether the Bluetooth device is out of: unpaired or unpaired or connected state

public String bltStatus(int status) {
        String a = "Unknown state";
        switch (status) {
            case BluetoothDevice.BOND_BONDING:
                a = "Connection";
                break;
            case BluetoothDevice.BOND_BONDED:
                a = "Connection completed";
                break;
            case BluetoothDevice.BOND_NONE:
                a = "Unconnected/Cancel connection";
                break;
        }
        return a;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

11. Bluetooth Click Event. Including Bluetooth on, off, searched, disconnected

/**
     * Bluetooth Operating Events
     *
     * @param context
     * @param status
     */
    public void clickBlt(Context context, int status) {
        switch (status) {
            case BltContant.BLUE_TOOTH_SEARTH://Search for Bluetooth devices and display results on Broadcast Receiver
                startSearthBltDevice(context);
                break;
            case BltContant.BLUE_TOOTH_OPEN://Local Bluetooth enabled
                if (getmBluetoothAdapter() != null)
                    getmBluetoothAdapter().enable();//Enable
                break;
            case BltContant.BLUE_TOOTH_CLOSE://Local Bluetooth Disabled
                if (getmBluetoothAdapter() != null)
                    getmBluetoothAdapter().disable();//Prohibit
                break;
            case BltContant.BLUE_TOOTH_MY_SEARTH://Local Bluetooth can be searched within 300 seconds
                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                context.startActivity(discoverableIntent);
                break;
            case BltContant.BLUE_TOOTH_CLEAR://Local Bluetooth Closes Current Connection
                try {
                    if (getmBluetoothSocket() != null)
                        getmBluetoothSocket().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

So far, Bluetooth has been written down from opening to connecting. Finally, let's sum up.
When we get the Bluetooth socket object, we can use socket programming to transfer data between two Bluetooth. It can even monitor the pause/play/volume keys of Bluetooth headphones and other clicks within the program.

Specific Bluetooth operation, I will put it in demo for everyone to learn.

demo download

(function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(′\n′).length;varnumbering = $('
    ').addClass('pre-numbering').hide(); (this).addClass(′has−numbering′).parent().append(numbering); for (i = 1; i

    Posted by poe on Mon, 25 Mar 2019 07:54:30 -0700