Connecting Devices Using Client and Server Architecture in Android: Part 2

Introduction

 
In the previous article, we saw that one is the client and another is the server because we are following the client and server architecture. We are very familiar with the traditional client and server architecture in which one is the server and another one is the client. Using the MAC address of the devices we can do the communication. Capable hardware can be simulated by this capable software, in other words, an Android application.
 
After the successful connection between two devices, each one will have a connected BluetoothSocket. The method we will use to transfer the data is the same as what we do in networking concepts of Java. Let us have a look at the points I will explain.
  • Get the InputStream and outPutStream that handle transmission through the socket via getInputstream() and getOutputStream, respectively.
     
  • For reading and writing data to the streams with read(byte[ ]) and write([ ]).
Note: the read() and write() methods are blocking calls. read(byte[]) will block the call until there is something to read from the stream. These methods just block the flow of control if the remote or any associated device is not calling.
 
Let us have a look at the example that shows the code as in the following.
 
Code
  1. private class ConnectedThread extends Thread {    
  2.     private final BluetoothSocket mmSocket;    
  3.     private final InputStream mmInStream;    
  4.     private final OutputStream mmOutStream;    
  5.      
  6.     public ConnectedThread(BluetoothSocket socket) {    
  7.         mmSocket = socket;    
  8.         InputStream tmpIn = null;    
  9.         OutputStream tmpOut = null;    
  10.      
  11.         // Get the input and output streams, using temp objects because    
  12.         // member streams are final    
  13.         try {    
  14.             tmpIn = socket.getInputStream();    
  15.             tmpOut = socket.getOutputStream();    
  16.         } catch (IOException e) { }    
  17.      
  18.         mmInStream = tmpIn;    
  19.         mmOutStream = tmpOut;    
  20.     }    
  21.      
  22.     public void run() {    
  23.         byte[] buffer = new byte[1024];  // buffer store for the stream    
  24.         int bytes; // bytes returned from read()    
  25.      
  26.         // Keep listening to the InputStream until an exception occurs    
  27.         while (true) {    
  28.             try {    
  29.                 // Read from the InputStream    
  30.                 bytes = mmInStream.read(buffer);    
  31.                 // Send the obtained bytes to the UI activity    
  32.                 mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)    
  33.                         .sendToTarget();    
  34.             } catch (IOException e) {    
  35.                 break;    
  36.             }    
  37.         }    
  38.     }    
  39.      
  40.     /* Call this from the main activity to send data to the remote device */    
  41.     public void write(byte[] bytes) {    
  42.         try {    
  43.             mmOutStream.write(bytes);    
  44.         } catch (IOException e) { }    
  45.     }    
  46.      
  47.     /* Call this from the main activity to shutdown the connection */    
  48.     public void cancel() {    
  49.         try {    
  50.             mmSocket.close();    
  51.         } catch (IOException e) { }    
  52.     }    
  53. }   

    Analysis

     
    Here the constructor acquires the necessary streams and once executed the thread is waiting for data to come through the InputStream. The thread cancel() method is important so that the connection can be terminated at any time by closing the BluetoothSocket. This should always be called when you are done using the Bluetooth connection.
     

    Exploring the profiles

     
    Bluetooth support for profiles was added by the Android version 3.0 Bluetooth API. According to Google, a Bluetooth profile is a wireless interface specification for Bluetooth-based communication between devices. An example is a Hands-Free profile. For a mobile phone to connect to a wireless headset, both devices must support the Hands-Free profile.
     
    The Interface BluetoothProfile can be implemented in their own classes to support a specific profile, a Bluetooth profile. The Android Bluetooth API provides implementations for the following Bluetooth profiles.
     

    Headset

     
    The Headset profile provides support for Bluetooth headsets to be used with mobile phones. Android provides the BluetoothHeadset class for use as a proxy for controlling the Bluetooth Headset Service via Inter-Process Communication (IPC). This includes both Bluetooth Headset and Hands-Free (v1.5) profiles. The BluetoothHeadset class includes support for AT commands. For more discussion of this topic, see Vendor-specific AT commands.
     

    A2DP

     
    The Advanced Audio Distribution Profile (A2DP) profile defines how high-quality audio can be streamed from one device to another over a Bluetooth connection. Android provides the BluetoothA2dp class that is a proxy for controlling the Bluetooth A2DP Service via IPC that is quite interesting.
     

    Health Device

     
    Let us consider the fact that devices are used for a heart pressure checker and blood pressure checker using the Bluetooth protocol called health device. Note that these values are also referenced in the ISO/IEEE 11073-20601 [7] specification as MDC_DEV_SPEC_PROFILE_* in the Nomenclature Codes.
     
    Working with a Profile
    • First get the default adapter, as described in Setting Up Bluetooth.
       
    • Use getProfileProxy() to establish a connection to the profile proxy object associated with the profile.
       
    • We must Set up a BluetoothProfile.ServiceListener. This listener will notify BluetoothProfile IPC clients when they have been connected to or disconnected from the service.
       
    • Then, In onServiceConnected(), get a handle to the profile proxy object.
       
    • Once you have the profile proxy object, we can use it to monitor the state of the connection and perform other operations that are relevant to that profile.
       
    • Let us have a look at the code below to understand how to connect to a BluetoothHeadset proxy object so that you can control the Headset profile.
    Code
    1. BluetoothHeadset mBluetoothHeadset;    
    2.      
    3. // Get the default adapter    
    4. BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();    
    5.      
    6. // Establish connection to the proxy.    
    7. mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);    
    8.      
    9. private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {    
    10.     public void onServiceConnected(int profile, BluetoothProfile proxy) {    
    11.         if (profile == BluetoothProfile.HEADSET) {    
    12.             mBluetoothHeadset = (BluetoothHeadset) proxy;    
    13.         }    
    14.     }    
    15.     public void onServiceDisconnected(int profile) {    
    16.         if (profile == BluetoothProfile.HEADSET) {    
    17.             mBluetoothHeadset = null;    
    18.         }    
    19.     }    
    20. };    
    21.      
    22. // ... call functions on mBluetoothHeadset    
    23.      
    24. // Close proxy connection after use.    
    25. mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);   
    Creating an HDP Application
     
    Here is the basic procedure involved in creating an Android HDP application:
    • Get a reference to the BluetoothHealth proxy object 
       
      Similar to a regular headset and A2DP profile devices as we already have seen above, one must call getProfileProxy() with BluetoothProfile. ServiceListener and the HEALTH profile types to establish a connection with the profile proxy object.
    • Create a BluetoothHealthCallback and register an application configuration (BluetoothHealthAppConfiguration) that acts as a health sink in the Android mechanism procedure.
    • Establish a connection to a health device. Some devices will initiate the connection. It is unnecessary to carry out this step for those devices.
    • When connected successfully to a health device, read/write to the health device using the file descriptor. The received data needs to be interpreted using a health manager that implements the IEEE 11073-xxxxx specifications.
    • When done, close the health channel and unregister the application. The channel also closes when there is extended inactivity.

    Summary

     
    This article illustrates the management of the connections and the profiles of Bluetooth. This article shows the connection between the devices along with their profiles and the basics of streaming data using Android.


    Similar Articles