Android Open Source - BLEConnector B L E Connector






From Project

Back to project page BLEConnector.

License

The source code is released under:

MIT License

If you think the Android project BLEConnector listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.felhr.bleconnector;
// www  .  j  a  v a2s  .c om
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;

public class BLEConnector 
{
  public static final String ACTION_BROADCAST_UUIDS = "com.felhr.bleconnector.action_broadcast_uuids";
  public static final String ACTION_DEVICE_CONNECTED = "com.felhr.bleconnector.action_device_connected";
  public static final String ACTION_DEVICE_SPOTTED = "com.felhr.bleconnector.action_device_spotted";
  public static final String ACTION_NO_CHARACTERISTIC = "com.felhr.bleconnector.action_no_characteristic";
  public static final String ACTION_NO_SERVICE = "com.felhr.bleconnector.action_no_service";
  public static final String ACTION_SCANNING_TERMINATED = "com.felhr.bleconnector.action_scanning_terminated";
  public static final String ACTION_NOTIFICATIONS_ENABLED = "com.felhr.bleconnector.action_notifications_enabled";
  
  public static final String UUIDS_TAG = "com.felhr.bleconnector.uuids_tag";
  public static final String DEVICE_TAG = "com.felhr.bleconnector.device_tag";
  public static final String ADDRESS_TAG = "com.felhr.bleconnector.address_tag";
  public static final String RSSI_TAG = "com.felhr.bleconnector.rssi_tag";
  
  // Bluetooth Low Energy Assigned UUIDS
  private static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); // TO DO
  
  private int connectMode; // 0 if you are going to spot devices only, 1 if you are going to perform a connection attempt with service and characteristic
               // 2 connection attempt with an specified service, 3 connection attempt without any specified service
  private Context context;
  private Handler mHandler;
  private BluetoothAdapter bleAdapter;
  private WorkerThread workerThread;
  private int bufferSize;
  private boolean isScanning;
  private AtomicBoolean operationReady;
  private Object objectMonitor;
  
  private BLEConnectedDevices connectedDevices; //Internally it is a hashtable
  private Hashtable<String,BLEDevice> spottedDevices;
  
  private UUID requestedService;
  private UUID requestedCharacteristic;
  
  private BLEBuffer buffer;

  public BLEConnector(Context context)
  {
    this.context = context;
    bufferSize = 128;
    objectMonitor = new Object();
    buffer = new BLEBuffer(bufferSize);
    connectedDevices = new BLEConnectedDevices();
    spottedDevices = new Hashtable<String,BLEDevice>();
    mHandler = new Handler();
    workerThread = new WorkerThread();
    workerThread.start();
    operationReady = new AtomicBoolean(true);
    final BluetoothManager bluetoothManager =
        (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    bleAdapter = bluetoothManager.getAdapter();
  }

  /* Public Methods */
  
  public void findBLEDevices(long scanTime)
  {
    spottedDevices.clear();
    connectMode = 0;
    startScan(scanTime);
  }
  
  public boolean connect(String deviceAddress, UUID uuidService, UUID uuidCharacteristic)
  {
    BLEDevice bleDevice = spottedDevices.get(deviceAddress);
    connectMode = 1;
    if(bleDevice != null)
    {
      requestedService = uuidService;
      requestedCharacteristic = uuidCharacteristic;
      bleDevice.getDevice().connectGatt(context, false, mGattCallback);
      return true;
    }else
    {
      return false;
    }
  }
  
  public boolean connect(String deviceAddress, UUID uuidService)
  {
    BLEDevice bleDevice = spottedDevices.get(deviceAddress);
    connectMode = 2;
    if(bleDevice != null)
    {
      requestedService = uuidService;
      bleDevice.getDevice().connectGatt(context, false, mGattCallback);
      return true;
    }else
    {
      return false;
    }
  }
  
  public boolean connect(String deviceAddress)
  {
    BLEDevice bleDevice = spottedDevices.get(deviceAddress);
    connectMode = 3;
    if(bleDevice != null)
    {
      bleDevice.getDevice().connectGatt(context, false, mGattCallback);
      return true;
    }else
    {
      return false;
    }
  }
  
  public UUID[] listOfServices(String deviceAddress)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    if(device == null)
      return null;
    List<BluetoothGattService> servicesList = device.getAllServices();
    UUID[] uuids = new UUID[servicesList.size()];
    for(int i=0;i<=servicesList.size()-1;i++)
    {
      BluetoothGattService service = servicesList.get(i);
      uuids[i] = service.getUuid();
    }
    return uuids;
  }
  
  public UUID[] listOfCharacteristics(String deviceAddress, UUID uuidService)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    if(device == null)
      return null;
    BluetoothGattService service = device.getGatt().getService(uuidService);
    List<BluetoothGattCharacteristic> characteristicsList = service.getCharacteristics();
    UUID[] uuids = new UUID[characteristicsList.size()];
    for(int i=0;i<=characteristicsList.size()-1;i++)
    {
      BluetoothGattCharacteristic characteristic = characteristicsList.get(i);
      uuids[i] = characteristic.getUuid();
    }
    return uuids;
  }
  
  public boolean setService(String deviceAddress, UUID uuidService)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    BluetoothGattService service = device.getGatt().getService(uuidService);
    if(service == null)
      return false;
    connectedDevices.get(deviceAddress).setService(service);
    return true;
  }
  
  public boolean setCharacteristic(String deviceAddress, UUID uuidCharacteristic)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    BluetoothGattService service = device.getService();
    BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuidCharacteristic);
    if(characteristic == null)
      return false;
    connectedDevices.get(deviceAddress).setCharacteristic(characteristic);
    return true;
  }
  
  public void writeCharacteristic(String deviceAddress, byte[] message)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    buffer.putToOutput(new QueuedMessage(message,device));
  }
  
  public boolean registerForNotifications(String deviceAddress, BLENotificationCallback mCallback)
  {
    BLEConnectedDevice device = connectedDevices.get(deviceAddress);
    BluetoothGattCharacteristic characteristic = device.getCharacteristic();
    if(characteristic != null)
    {
      BluetoothGatt gatt = device.getGatt();
      gatt.setCharacteristicNotification(characteristic, true);
      BluetoothGattDescriptor clientCharConfigDescriptor = 
          characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIGURATION);
      clientCharConfigDescriptor.setValue(isSetProperty(PropertyType.NOTIFY,characteristic.getProperties()) ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
          : BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
      workerThread.setCallback(mCallback);
      device.notificationsOn();
      connectedDevices.put(deviceAddress, device);
      return gatt.writeDescriptor(clientCharConfigDescriptor);
    }else
    {
      return false;
    }
  }

  /* Private Functions */
  
  private void startScan(long scanTime)
  {
    if(bleAdapter != null && bleAdapter.isEnabled())
    {
      mHandler.postDelayed(new Runnable()
      {
        @Override
        public void run() 
        {
          if(isScanning)
          {
            bleAdapter.stopLeScan(mScanCallback);
            isScanning = false;
            Intent intent = new Intent(ACTION_SCANNING_TERMINATED);
            context.sendBroadcast(intent);
          }
        }
      }, scanTime);
      isScanning = true;
      bleAdapter.startLeScan(mScanCallback);
    }
  }
  
  /* Bluetooth Low Energy API Callbacks */

  private final BluetoothAdapter.LeScanCallback mScanCallback = new BluetoothAdapter.LeScanCallback()
  {

    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) 
    {
      if(connectMode == 0) // Store a spotted device
      {
        String deviceAddress = device.getAddress();
        if(!spottedDevices.containsKey(deviceAddress))
        {
          spottedDevices.put(deviceAddress, new BLEDevice(device, rssi, scanRecord));
          Intent intent = new Intent(ACTION_DEVICE_SPOTTED);
          intent.putExtra(DEVICE_TAG,device.getName());
          intent.putExtra(ADDRESS_TAG, device.getAddress());
          intent.putExtra(RSSI_TAG, rssi);
          context.sendBroadcast(intent);
        }
      }else 
      {
        // Connect to an array of advertised UUIDs.
      }
      
    }

  };
  
  private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
  {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
    {
      if(status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED)
      {
        BLEDevice device = spottedDevices.get(gatt.getDevice().getAddress());
        BLEConnectedDevice connectedDevice = new BLEConnectedDevice(device);
        connectedDevice.setGatt(gatt);
        connectedDevice.notificationsOff();
        connectedDevices.put(gatt.getDevice().getAddress(), connectedDevice);
        gatt.discoverServices();
        
      }else if(status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_DISCONNECTED)
      {
        connectedDevices.remove(gatt.getDevice().getAddress());
      }
    }
    
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status)
    {
      if(connectMode == 1)
      {
        BluetoothGattService service = gatt.getService(requestedService);
        if(service != null)
        {
          BLEConnectedDevice bleDevice  = connectedDevices.get(gatt.getDevice().getAddress());
          bleDevice.setService(service);
          String name = bleDevice.getDevice().getName();
          String address = bleDevice.getDevice().getAddress();

          BluetoothGattCharacteristic characteristic = service.getCharacteristic(requestedCharacteristic);
          bleDevice.setCharacteristic(characteristic);
          if(characteristic != null)
          {
            bleDevice.setCharacteristic(characteristic);
            Intent intent = new Intent(ACTION_DEVICE_CONNECTED);
            intent.putExtra(DEVICE_TAG,name);
            intent.putExtra(ADDRESS_TAG, address);
            connectedDevices.put(bleDevice.getDevice().getAddress(), bleDevice);
            context.sendBroadcast(intent);

          }else
          {
            connectedDevices.remove(gatt.getDevice().getAddress());
            Intent intent = new Intent(ACTION_NO_CHARACTERISTIC);
            context.sendBroadcast(intent);
            gatt.close();
          }
        }else
        {
          connectedDevices.remove(gatt.getDevice().getAddress());
          Intent intent = new Intent(ACTION_NO_SERVICE);
          context.sendBroadcast(intent);
          gatt.close();
        }
      }else if(connectMode == 2)
      {
        BluetoothGattService service = gatt.getService(requestedService);
        if(service != null)
        {
          BLEConnectedDevice bleDevice  = connectedDevices.get(gatt.getDevice().getAddress());
          bleDevice.setService(service);
          String name = bleDevice.getDevice().getName();
          String address = bleDevice.getDevice().getAddress();

          Intent intent = new Intent(ACTION_DEVICE_CONNECTED);
          intent.putExtra(DEVICE_TAG,name);
          intent.putExtra(ADDRESS_TAG, address);
          connectedDevices.put(bleDevice.getDevice().getAddress(), bleDevice);
          context.sendBroadcast(intent);
        }else
        {
          connectedDevices.remove(gatt.getDevice().getAddress());
          Intent intent = new Intent(ACTION_NO_SERVICE);
          context.sendBroadcast(intent);
          gatt.close();
        }
      }else if(connectMode == 3)
      {
        BLEConnectedDevice bleDevice  = connectedDevices.get(gatt.getDevice().getAddress());
        String name = bleDevice.getDevice().getName();
        String address = bleDevice.getDevice().getAddress();

        Intent intent = new Intent(ACTION_DEVICE_CONNECTED);
        intent.putExtra(DEVICE_TAG,name);
        intent.putExtra(ADDRESS_TAG, address);
        context.sendBroadcast(intent);
      }
    }
    
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
    {
      synchronized(objectMonitor)
      {
        connectedDevices.setAllNotifications(true);
        operationReady.set(true);
        objectMonitor.notify();
      }  
    }
    
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
    {
      byte[] data = characteristic.getValue();
      String deviceAddress = gatt.getDevice().getAddress();
      workerThread.receiveNotifications(deviceAddress, data);
    }
    
    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
    {
      BLEConnectedDevice bleDevice  = connectedDevices.get(gatt.getDevice().getAddress());
      String name = bleDevice.getDevice().getName();
      String address = bleDevice.getDevice().getAddress();
      
      Intent intent = new Intent(ACTION_NOTIFICATIONS_ENABLED);
      intent.putExtra(DEVICE_TAG,name);
      intent.putExtra(ADDRESS_TAG, address);
      context.sendBroadcast(intent);
    }
  };
  
  
  /* Operation Threads*/
  
  private class WorkerThread extends Thread
  {
    private BLENotificationCallback mCallback;
    private boolean started;
    
    public WorkerThread()
    {
      started = true;
    }
    
    public void setCallback(BLENotificationCallback mCallback)
    {
      this.mCallback = mCallback;
    }
    
    @Override
    public void run()
    {
      sendMessage();
    }
    
    private void sendMessage()
    {
      while(started)
      {
        QueuedMessage message = buffer.getFromOutput();
        synchronized(objectMonitor)
        {
          while(!operationReady.get())
          {
            try 
            {
              objectMonitor.wait();
            } catch (InterruptedException e) 
            {
              e.printStackTrace();
            }
          }
        }
        connectedDevices.setAllNotifications(false);
        BluetoothGatt gatt = message.getDevice().getGatt();
        BluetoothGattCharacteristic characteristic = message.getDevice().getCharacteristic();
        characteristic.setValue(message.getMessage());
        operationReady.set(false);
        gatt.writeCharacteristic(characteristic);
      }
    }
    
    public void receiveNotifications(String deviceAddress, byte[] data)
    {
      mCallback.onReceivedNotification(deviceAddress, data);
    }
  }
  
  /* Inner classes and Enums */
  
  protected class QueuedMessage
  {
    private byte[] message;
    private BLEConnectedDevice device;
    
    public QueuedMessage(byte[] message, BLEConnectedDevice device)
    {
      this.message = message;
      this.device = device;
    }

    public byte[] getMessage() 
    {
      return message;
    }

    public void setMessage(byte[] message) 
    {
      this.message = message;
    }

    public BLEConnectedDevice getDevice() 
    {
      return device;
    }

    public void setDevice(BLEConnectedDevice device) 
    {
      this.device = device;
    }  
  }
  
  public interface BLENotificationCallback
  {
    public void onReceivedNotification(String addressDevice, byte[] data);
  }
  
  private enum PropertyType
  {
        BROADCAST(1),
        READ(2),
        WRITE_NO_RESPONSE(4),
        WRITE(8),
        NOTIFY(16),
        INDICATE(32),
        SIGNED_WRITE(64),
        EXTENDED_PROPS(128);

        private final int value;

        private PropertyType(int value)
        {
            this.value = value;
        }

        public int getValue() 
        {
            return value;
        }
    }
  
   private boolean isSetProperty(PropertyType property, int properties) 
   {
     boolean isSet = ((properties >> (property.ordinal())) & 1) != 0;
     return isSet;
   }
}




Java Source Code List

com.felhr.bleconnector.BLEAdvertisingParser.java
com.felhr.bleconnector.BLEBuffer.java
com.felhr.bleconnector.BLEConnectedDevice.java
com.felhr.bleconnector.BLEConnectedDevices.java
com.felhr.bleconnector.BLEConnector.java
com.felhr.bleconnector.BLEDevice.java