The Bluetooth chat software based on Android Classic Bluetooth currently only supports one-to-one real-time communication, file transfer, friend addition, friend group, and friend online status update. The message sending mode supports text and emoticons.

Project address: github.com/xiaoyaoyou1… (Fork is welcome)

prospects

As a small range wireless connection technology, Bluetooth technology can realize convenient, flexible, safe, low-cost and low-power data and voice communication between devices. It is one of the mainstream technologies to realize wireless personal LAN at present. At the same time, the Bluetooth system works in the way of self-group networking. Each Bluetooth device can realize the function of route selection in the network, which can form a mobile self-group network. Bluetooth’s features, which in many ways match the concepts of Ad Hoc and WPAN, show its true potential. Moreover, the connection of Bluetooth with other networks can lead to a wider range of applications, such as access to the Internet, PSTN or public mobile networks, which can make the application easier or bring greater benefits to users.

Bluetooth chat as a local area network chat software, in the office intensive, to achieve rapid and stable real-time communication or more practical value. At present, Bluetooth technology develops rapidly, the transmission rate of 5.0 has reached 2Mbps, the transmission level has reached lossless level, and the effective working distance can reach 300 meters. Bluetooth networking technology is also being further updated. I believe that it will not be long before a very mature scheme comes out, so that it can realize the real-time chat function of multiple people online. Break the boundaries of one-to-many real-time chat.

Functions overview

Bluetooth chat function is mainly divided into the following modules: message module, friend module and personal module.

Friends module

Support nearby friends to add, delete friends, friends group display, friends up and down reminding, friends nickname and group name modification.

Operation process

Enable device discoverability

To make the local device discoverable by other devices, call the startActivityForResult(Intent, int) method with ACTION_REQUEST_DISCOVERABLE action Intent. This method makes a request to the system Settings to enable discoverable mode. By default, the device is in discoverable mode for 120 seconds. You can define different durations by adding the EXTRA_DISCOVERABLE_DURATION additional field to an Intent object. The maximum duration that an application can set is 3600 seconds, with 0 meaning the device is always discoverable. Any value less than 0 or greater than 3600 seconds is automatically set to 120 seconds. For example, the following code sets the duration to 300 seconds:

Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
Copy the code

A dialog box is displayed when the application user enables the discoverable mode of the device. If the response is “Yes,” the device’s discoverable mode lasts for the specified time, and your Activity receives a call to the onActivityResult() callback method with the resulting code equal to the discoverable device duration. If the user responds “No” or an error occurs, the resulting code is equal to RESULT_CANCELED. In discoverable mode, the device quietly leaves the mode in place for a specified period of time. If you want to be notified when the discoverable mode changes, you can register an Intent broadcast of type ACTION_SCAN_MODE_CHANGED. The EXTRA_SCAN_MODE and EXTRA_PREVIOUS_SCAN_MODE additional fields are included in the Intent object, which tell you the old and new scan modes, respectively. Each of their possible values is: SCAN_MODE_CONNECTABLE_DISCOVERABLE, SCAN_MODE_CONNECTABLE, or SCAN_MODE_NONE, which indicate whether the device is in discoverable mode or in discoverable mode but can still receive connections, respectively, Or it cannot receive connections in discoverable mode. If you want to initialize a connection to a remote device, you do not need to enable device revisibility. Discoverability needs to be enabled only if you want your application to receive input connections as a server, because remote devices must be able to discover it before connecting to your device.

Connect devices (friends establish communication channels)

When you want to connect two devices, one must act as a server by holding an open BluetoothServerSocket object. The purpose of the service socket is to listen for incoming connection requests and, when a connection request is received, provide a BluetoothSocket connection object. The BluetoothServerSocket can (and should) be deprecated when you get the BluetoothServerSocket object, unless you want to receive more connections. The following service is to establish a socket and receive a link to the basic process: 1, call listenUsingRfcommWithServiceRecord (String, UUID) method to obtain a BluetoothServerSocket object. The String argument in this method is an identifiable name of your server, which the system automatically writes to the Service Discovery Protocol (SDP) database entity on the device (the name is arbitrary, and you can simply use the name of your application). The UUID parameter is also included in the SDP entity and is the basic protocol for connecting to the client device. That is, when a client attempts to connect to a server, it carries a UUID that is unique to the server it wants to connect to. Connections can only be accepted if these UUID’s match exactly. 2. Initiate the connection request by calling the Accept () method. This is a blocking call. This method returns only if the connection is accepted or if an exception occurs. A connection is accepted only if the UUID carried by the remote device sending the connection request matches a UUID registered by the listening service socket. The accept() method returns a connected BluetoothSocket object. 3. Call close() unless you want to receive other connections. This method frees the service socket and all the resources it consumes, but does not close the BluetoothSocket object returned by the connected accept() method. Unlike TCP/IP, each RFCOMM channel is only allowed to connect to one client at a time, so in most cases it makes sense to call the close() method of the BluetoothServerSocket object immediately after receiving a connection socket. Here are the listening threads implemented by the above procedure:

public class AcceptThread extends Thread {

    private BluetoothChatHelper mHelper;
    private final BluetoothServerSocket mServerSocket;
    private String mSocketType;

    public AcceptThread(BluetoothChatHelper bluetoothChatHelper, boolean secure) {
        mHelper = bluetoothChatHelper;
        BluetoothServerSocket tmp = null;
        mSocketType = secure ? "Secure" : "Insecure";

        try {
            if (secure) {
                tmp = mHelper.getAdapter().listenUsingRfcommWithServiceRecord(ChatConstant.NAME_SECURE, ChatConstant.UUID_SECURE);
            } else {
                tmp = mHelper.getAdapter().listenUsingInsecureRfcommWithServiceRecord(ChatConstant.NAME_INSECURE, ChatConstant.UUID_INSECURE);
            }
        } catch (IOException e) {
            BleLog.e("Socket Type: " + mSocketType + "listen() failed", e);
        }
        mServerSocket = tmp;
    }

    public void run() {
        BleLog.i("Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this);
        setName("AcceptThread" + mSocketType);

        BluetoothSocket socket = null;

        while (mHelper.getState() != com.vise.basebluetooth.common.State.STATE_CONNECTED) {
            try {
                BleLog.i("wait new socket:" + mServerSocket);
                socket = mServerSocket.accept();
            } catch (IOException e) {
                BleLog.e("Socket Type: " + mSocketType + " accept() failed", e);
                break;
            }
            if (socket != null) {
                synchronized (this) {
                    if(mHelper.getState() == com.vise.basebluetooth.common.State.STATE_LISTEN
                            || mHelper.getState() == com.vise.basebluetooth.common.State.STATE_CONNECTING){
                        BleLog.i("mark CONNECTING");
                        mHelper.connected(socket, socket.getRemoteDevice(), mSocketType);
                    } else if(mHelper.getState() == com.vise.basebluetooth.common.State.STATE_NONE
                            || mHelper.getState() == com.vise.basebluetooth.common.State.STATE_CONNECTED){
                        try {
                            socket.close();
                        } catch (IOException e) {
                            BleLog.e("Could not close unwanted socket", e);
                        }
                    }
                }
            }
        }
        BleLog.i("END mAcceptThread, socket Type: " + mSocketType);
    }

    public void cancel() {
        BleLog.i("Socket Type" + mSocketType + "cancel " + this);
        try {
            mServerSocket.close();
        } catch (IOException e) {
            BleLog.e("Socket Type" + mSocketType + "close() of server failed", e);
        }
    }
}
Copy the code

The following is a basic connection process: 1, by calling the BluetoothDevice of createRfcommSocketToServiceRecord (UUID) method, get a BluetoothSocket object. This method initializes a BluetoothSocket object connected to the BluetoothDevice object. The UUID parameter passed to this method must match the UUID used by the server device to open the BluetoothServerSocket object. Simply hardcode it in your application and if it matches, the server and client code can apply the BluetoothSocket object. 2. Initialize the connection by calling connect(). In this call, an SDP query is performed on a remote device to find a matching UUID. If the query is successful and the remote device receives the connection request, it shares the USE of the RFCOMM channel during the connection and the connect() method returns. This method is a blocking call. If, for some reason, the connection fails or times out (after about 12 seconds), an exception is thrown. Here is the thread that implements the above process:

public class ConnectThread extends Thread { private BluetoothChatHelper mHelper; private final BluetoothSocket mSocket; private final BluetoothDevice mDevice; private String mSocketType; public ConnectThread(BluetoothChatHelper bluetoothChatHelper, BluetoothDevice device, boolean secure) { mHelper = bluetoothChatHelper; mDevice = device; BluetoothSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure"; try { if (secure) { tmp = device.createRfcommSocketToServiceRecord(ChatConstant.UUID_SECURE); } else { tmp = device.createInsecureRfcommSocketToServiceRecord(ChatConstant.UUID_INSECURE); } } catch (IOException e) { BleLog.e("Socket Type: " + mSocketType + "create() failed", e); } mSocket = tmp; } public void run() { BleLog.i("BEGIN mConnectThread SocketType:" + mSocketType); setName("ConnectThread" + mSocketType); mHelper.getAdapter().cancelDiscovery(); try { mSocket.connect(); } catch (IOException e) { try { mSocket.close(); } catch (IOException e2) { BleLog.e("unable to close() " + mSocketType + " socket during connection failure", e2); } mHelper.connectionFailed(); return; } synchronized (this) { mHelper.setConnectThread(null); } mHelper.connected(mSocket, mDevice, mSocketType); } public void cancel() { try { mSocket.close(); } catch (IOException e) { BleLog.e("close() of connect " + mSocketType + " socket failed", e); }}}Copy the code

The cancelDiscovery() method is called before the connection is established. This method should always be called before connecting, and it is safe to not actually check whether the Bluetooth discovery processing is running (if you want to check, call the isparent () method).

About the author

Web site:www.xiaoyaoyou1212.com

Blog:Blog.csdn.net/xiaoyaoyou1…