Android Communication--Bluetooth

Posted by kawai84 on Fri, 17 May 2019 11:59:10 +0200

               

Usually, our main operations on Bluetooth are: turning on and off Bluetooth, searching for peripherals, being discovered by peripherals, getting data transmission between paired devices, and Bluetooth devices.

1. Turn on Bluetooth (of course, first make sure your mobile phone has a Bluetooth device)

Bluetooth devices are mainly divided into two parts, one for local devices and the other for remote devices.

  • Bluetooth Adapter - Local device, you need a Bluetooth Adapter instance to operate on Bluetooth first.The common methods are as follows:
    • cancelDiscovery() - Cancels the search operation for the local Bluetooth device, and stops the search operation if the local device is searching.
    • Disable() - Turn off Bluetooth devices.
    • Enable() - Turn on the Bluetooth device.Believe that everyone has experienced opening Bluetooth. Usually a window pops up saying that you are requesting to open a Bluetooth device. Do you want to allow the cloud?
    • getAddress() - Get the MAC address of the Bluetooth device.
    • GetDefaultAdapter() - Get local Bluetooth devices
    • getName() - Get the name of the local Bluetooth
    • getRemoteDevice(String address) - Get a remote device based on its MAC address
    • startDiscovery() - Bluetooth devices start searching for peripherals
  • BuletoothDevice - A remote device.

It contains the same methods as Bluetooth Adapter and is no longer exhaustive.

View Code  // Get a local Bluetooth adapter instance             BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();             if(adapter!=null)             {                 if(!adapter.isEnabled())                 {                     //Request to turn on our Bluetooth device in this way                     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);                     startActivity(intent);                 }             }             else             {                 System.out.println("Local device driver exception!");             }

2. Search for peripherals

For Android lookup discovery Bluetooth devices using the Bluetooth Adapter class startDiscovery() method can execute an asynchronous method to get the peripheral Bluetooth devices, because it is an asynchronous method, we do not need to consider the thread blocking problem, the whole process takes about 12 seconds, at which time we can register a BroadcastReceiver object to receive the lookupFor Bluetooth device information, we filter ACTION_FOUND through Filter to get detailed information about each remote device, and Bluetooth Class of this device type containing each Bluetooth Device object and object can be obtained through Intent fields EXTRA_DEVICE and EXTRA_CLASS.

Implement your own BroadCastReceiver class and register it.

View Code      private class BluetoothReciever extends BroadcastReceiver {          @Override         public void onReceive(Context context, Intent intent) {             // TODO Auto-generated method stub             String action = intent.getAction();             if (BluetoothDevice.ACTION_FOUND.equals(action)) {                 BluetoothDevice device = intent                         .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                 System.out.println(device.getAddress());             }         }      }

IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);bluetoothReceive = new BluetoothReciever();registerReceiver(bluetoothReceive, intentFilter);

Since after registering a Receiver, the program does not know when to recycle it, we need to override the onDestroy() method of the Activity class ourselves.

@Override     protected void onDestroy() {         // TODO Auto-generated method stub         unregisterReceiver(bluetoothReceive);         super.onDestroy();     }

3. Discovered by peripheral devices

If the user is required to confirm the operation and does not need to get the underlying Bluetooth service instance, the ACTION_REQUEST_DISCOVERABLE parameter can be passed through an Intent, where the startActivity is used to request the opening.

Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); //The parameter 50 represents how many seconds a Bluetooth device will be discovered.  discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 50);             startActivity(discoverableIntent);

4. Pairing

The pairing operation is usually done manually after the device is discovered and the system automatically pairs up after selection.We can get paired devices by:

View Code                  //Get the device that has been paired with this device using the getBondedDevices method                 Set<BluetoothDevice> device= adapter.getBondedDevices();                 if(device.size()>0)                 {                     for(Iterator iterator=device.iterator();iterator.hasNext();)                     {                         BluetoothDevice bluetoothDevice=(BluetoothDevice)iterator.next();                         System.out.println(bluetoothDevice.getAddress());                     }                 }

5. Data Exchange

After seeing the previous startup, discovery/search, and pairing operations, here are the data transfer issues.

In Android systems, the problem of data transmission between Bluetooth devices is very similar to our network programming on PC. One side listens for connection requests on Client side as Server side, after the connection is established between them, the data exchange operation can be carried out using normal data transmission method.In this process, I need to use two classes, Bluetooth ServerSocket and Bluetooth Socket, to build the Server and Client ends, and some knowledge about Stream.

  • Bluetooth ServerSocket - Server (listener, listener, requester)
    • Accept() - Blocks the host thread until a client request is received.Returns the BluetoothSocket object.Because of this
    • Accept(int timeout) - Blocks the host thread until a client request is received or the wait time exceeds timeout.Returns the BluetoothSocket object.
    • Close() - Close the Bluetooth ServerSocket listener.

You can see that the Accept method is a blocking method, so multithreaded knowledge is generally required for development.The multithreaded knowledge of JAVA can be viewed in the JDK help documentation of JAVA, which is relatively simple for simple application.

  • Bluetooth Socket - Client (Requestor)
    • Close() - Close the Bluetooth Socket requester.
    • Connect() - Actively initiates a connection request to the server (listener).

With these two types in mind, you can start building your own Server and Client ends.

If a device needs to be connected to two or more devices, it needs to be transmitted as a server, and the server-side socket responds accordingly when it accepts a Bluetooth Socket connection request from a client.The server socket will listen for incoming connection requests, and once the connection is accepted, a Bluetooth Socket will be generated.

  • Create a Server

Create a new ServerSocket using the listenUsingRfcommWithServiceRecord method of the Bluetooth Adapter class.One parameter in listenUsingRfcommWithServiceRecord is called UUID, which is a 128-bit string ID used to uniquely identify our Bluetooth service.You can use any UUID generator on the web to get a UUID for your program, and then use fromString to initialize a UUID.

Listens using the accept method of the ServerSocket instance, responds when a connection request with our initialized UUID parameter is heard, and returns a Bluetooth Socket object when the connection is successful.When the connection is complete, the close method is called to close the socket listening.

View Code      // ServerSocket wrapper class for Bluetooth     class BluetoothServer {         public BluetoothServer() throws IOException {         }          // To create a ServerSocket object, you need to use the adapter.listenUsingRfcommWithServiceRecord method // UUID can apply online         private BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myServerSocket",                         UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));         BluetoothSocket socket = serverSocket.accept();          void m() throws IOException {             if (socket != null) {                 InputStream inputStream = socket.getInputStream();                 int read = -1;                 final byte[] bytes = new byte[1024];                 for (; (read = inputStream.read(bytes)) > -1;) {                     final int count = read;                     Thread _start = new Thread(new Runnable() {                          @Override                         public void run() {                              // TODO Auto-generated method stub                             StringBuilder sb = new StringBuilder();                             for (int i = 0; i < count; i++) {                                 if (i > 0) {                                     sb.append(' ');                                 }                                 String _s = Integer.toHexString(bytes[i] & 0xFF);                                 if (_s.length() < 2) {                                     sb.append('0');                                 }                                 sb.append(_s);                             }                             System.out.println(sb.toString());                         }                     });                     _start.start();                 }             }         }     }

  • Create a Client

To create a client side, you first need to create a Bluetooth Socket instance using the createRfcommSocketToServiceRecord method of the Bluetooth Device instance.At the time of creation, the createRfcommSocketToServiceRecord method needs to be passed in the UUID value of our server.The Connect method of the Bluetooth Socket instance is then used to make the connection request to the Server side, and when the connection is successful, the transport channels on the Client side and the Server side are opened.The close method of the instance is used to close the connection after it is completed.

View Code  class BluetoothClient {         BluetoothDevice device = null;          //Pass in a BluetoothDevice instance through the constructor         public BluetoothClient(BluetoothDevice device) {             this.device = device;         }         BluetoothSocket socket = null;         void connetServer() throws IOException {             Thread _clientThread = new Thread(new Runnable() {                 public void run() {                     try {                         //A Bluetooth Socket instance with UUID can be returned by the Bluetooth Device instance's createRfcommSocketToServiceRecord method                         socket = device.createRfcommSocketToServiceRecord(UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));                     } catch (IOException e1) {                          // TODO Auto-generated catch block                         e1.printStackTrace();                     }                     try {                         socket.connect();                     } catch (IOException e1) {                          // TODO Auto-generated catch block                         e1.printStackTrace();                     }                     if (socket != null) {                         try {                             socket.close();                         } catch (Exception e) {                             // TODO: handle exception                         }                     }                 }             });             _clientThread.start();         }     }

getInputStream() - Obtains a readable stream that can still be obtained if the connection is unsuccessful, but an IOException exception is reported if it is operated on.Data that needs to be acquired externally is taken from the stream.

getOutputStrem() - Gets a writable stream that is still available if the connection is unsuccessful, but an IOException exception is reported if it is operated on.Data that needs to be transferred externally can be written to and transferred out of the stream.

The general flow of data transmission is as follows:

    • First, InputStream () and OutputStream () are used to manage data transmission.
    • Then, a thread is devoted to reading or writing data.This is important because both read(byte[]) and write(byte[]) methods are blocking calls.read(byte[]) reads data from an input stream (InputStream).write(byte[]) writes data to the OutputStream stream, which is generally not blocked, but is always blocked when the remote device's intermediate buffer is full and the other party does not call read(byte[]) in time.So the main loop in the newly opened thread will always be used to read data from InputStream.

Additionally, since Bluetooth devices are system devices, appropriate privilege support is required.Add permissions to the AndroidManifest.xml file.

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

Author: Libo@Deng 


Source: http://www.cnblogs.com/cxcco/ 

           

Topics: socket Android Mac Java