title: Android 4.3: How to connect to multiple Bluetooth Low Energy devices?
body: <p><strong>Task:</strong> </p>
  
  <p>I am developing an Android application that will need to simultaneously connect to multiple (identical, that can be differentiated via their ID) BLE chip devices in order to send and receive updates.  I have used the tutorials on Google's official web page: </p>
  
  <p><a href="http://developer.android.com/guide/topics/connectivity/bluetooth-le.html" rel="nofollow noreferrer">http://developer.android.com/guide/topics/connectivity/bluetooth-le.html</a></p>
  
  <p>This has helped me to create a DeviceScanActivity Java class that allows me to scan for and list all of the available BLE devices in close proximity, similarly to what most applications of this type currently do. I also found out that up to 7 external slaves can be connected to the same master device simultaneously. However, implementing this communication is still unclear for me. A useful link is: </p>
  
  <p><a href="https://stackoverflow.com/questions/21237093/android-4-3-how-to-connect-to-multiple-bluetooth-low-energy-devices">Android 4.3: How to connect to multiple Bluetooth Low Energy devices</a> </p>
  
  <p>However, it does not provide enough detail for me to understand how such an implementation works. </p>
  
  <p>I have been researching this topic for a while and was not able to find any example implementations. I am aware that this question has been asked a lot of times but there does not seem to be any working solution/ demo that is available online to make things more clear for me. I will appreciate it a lot if anyone can point me to a resource/ working solution that will explain in detail the steps that are necessary to modify my existing Java class in order to implement this functionality.</p>
  
  <p><strong>DeviceScanActivity.java</strong>:</p>
  
  <pre><code>import android.app.Activity;
  import android.app.ListActivity;
  import android.app.ProgressDialog;
  import android.bluetooth.BluetoothAdapter;
  import android.bluetooth.BluetoothDevice;
  import android.bluetooth.BluetoothManager;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.pm.PackageManager;
  import android.os.Bundle;
  import android.os.Handler;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.BaseAdapter;
  import android.widget.ListView;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import java.util.ArrayList;
  
  /**
   * Activity for scanning and displaying available Bluetooth LE devices.
   */
  public class DeviceScanActivity extends ListActivity {
      private LeDeviceListAdapter mLeDeviceListAdapter;
      private BluetoothAdapter mBluetoothAdapter;
      private boolean mScanning;
      private Handler mHandler;
  
      private static final int REQUEST_ENABLE_BT = 1;
      // Stops scanning after 10 seconds.
      private static final long SCAN_PERIOD = 10000;
  
      private static final String CONFIG_FILE = "file";
  
      private int _countClick = 0;
      private boolean experimenterMode = false;
      private String pairedDeviceAddress = "";
  
  
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          getActionBar().setTitle(R.string.title_devices);
          mHandler = new Handler();
  
          // Use this check to determine whether BLE is supported on the device.  Then you can
          // selectively disable BLE-related features.
          if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
              Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
              finish();
          }
  
          // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
          // BluetoothAdapter through BluetoothManager.
          final BluetoothManager bluetoothManager =
                  (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
          mBluetoothAdapter = bluetoothManager.getAdapter();
  
          // Checks if Bluetooth is supported on the device.
          if (mBluetoothAdapter == null) {
              Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
              finish();
              return;
          }
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.main, menu);
          if (!mScanning) {
              menu.findItem(R.id.menu_stop).setVisible(false);
              menu.findItem(R.id.menu_scan).setVisible(true);
              menu.findItem(R.id.menu_refresh).setActionView(null);
          } else {
              menu.findItem(R.id.menu_stop).setVisible(true);
              menu.findItem(R.id.menu_scan).setVisible(false);
              menu.findItem(R.id.menu_refresh).setActionView(
                      R.layout.actionbar_indeterminate_progress);
          }
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          switch (item.getItemId()) {
              case R.id.menu_scan:
                  mLeDeviceListAdapter.clear();
                  scanLeDevice(true);
                  break;
              case R.id.menu_stop:
                  scanLeDevice(false);
                  break;
              case android.R.id.home:
                  //onBackPressed();
                  _countClick++;
                  if(_countClick&gt;8)
                  {
                      toggleExperimenterMode();
                  }
                  return true;
          }
          return super.onOptionsItemSelected(item);
      }
  
      @Override
      protected void onResume() {
          super.onResume();
  
          // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
          // fire an intent to display a dialog asking the user to grant permission to enable it.
          if (!mBluetoothAdapter.isEnabled()) {
              if (!mBluetoothAdapter.isEnabled()) {
                  Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                  startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
              }
          }
  
          // Restore preferences
          SharedPreferences settings = getSharedPreferences(CONFIG_FILE, 0);
          experimenterMode = settings.getBoolean("experimenterMode", false);
          pairedDeviceAddress = settings.getString("pairedDeviceAddress", "");
  
          // Initializes list view adapter.
          mLeDeviceListAdapter = new LeDeviceListAdapter();
          setListAdapter(mLeDeviceListAdapter);
          scanLeDevice(true);
      }
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          // User chose not to enable Bluetooth.
          if (requestCode == REQUEST_ENABLE_BT &amp;&amp; resultCode == Activity.RESULT_CANCELED) {
              finish();
              return;
          }
          super.onActivityResult(requestCode, resultCode, data);
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          scanLeDevice(false);
          mLeDeviceListAdapter.clear();
      }
  
      @Override
      protected void onListItemClick(ListView l, View v, int position, long id) {
          final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
          if (device == null) return;
          connectToDevice(device);
      }
  
  
  
      private void connectToDevice(BluetoothDevice device){
          final Intent intent = new Intent(this, DeviceControlActivity.class);
          intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
          intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
          if (mScanning) {
              mBluetoothAdapter.stopLeScan(mLeScanCallback);
              mScanning = false;
          }
  
          SharedPreferences settings = getSharedPreferences(CONFIG_FILE, 0);
          SharedPreferences.Editor editor = settings.edit();
          editor.putString("pairedDeviceAddress", device.getAddress());
          editor.commit();
  
          startActivity(intent);
      }
  
      //---------------------------------------------------
  
      private void scanLeDevice(final boolean enable) {
          ProgressDialog progress;
          if (enable) {
              // Stops scanning after a pre-defined scan period.
              mHandler.postDelayed(new Runnable() {
                  @Override
                  public void run() {
                      mScanning = false;
                      mBluetoothAdapter.stopLeScan(mLeScanCallback);
                      invalidateOptionsMenu();
                  }
              }, SCAN_PERIOD);
  
              mScanning = true;
              mBluetoothAdapter.startLeScan(mLeScanCallback);
          } else {
              mScanning = false;
              mBluetoothAdapter.stopLeScan(mLeScanCallback);
  
          }
          invalidateOptionsMenu();
      }
  
      private void toggleExperimenterMode(){
          _countClick=0;
          experimenterMode = !experimenterMode;
          SharedPreferences settings = getSharedPreferences(CONFIG_FILE, 0);
          SharedPreferences.Editor editor = settings.edit();
          editor.putBoolean("experimenterMode", experimenterMode);
          editor.commit();
          String t = experimenterMode ? "You are now in Experimenter mode":"You are now in User mode";
          Toast.makeText(this, t, Toast.LENGTH_SHORT).show();
      }
  
      // Adapter for holding devices found through scanning.
      private class LeDeviceListAdapter extends BaseAdapter {
          private ArrayList&lt;BluetoothDevice&gt; mLeDevices;
          private LayoutInflater mInflator;
  
          public LeDeviceListAdapter() {
              super();
              mLeDevices = new ArrayList&lt;BluetoothDevice&gt;();
              mInflator = DeviceScanActivity.this.getLayoutInflater();
          }
  
          public void addDevice(BluetoothDevice device) {
              if(!mLeDevices.contains(device)) {
                  mLeDevices.add(device);
              }
              if (!experimenterMode &amp;&amp; ! pairedDeviceAddress.isEmpty()) {
                  if (device.getAddress().equals(pairedDeviceAddress)) {
                      connectToDevice(device);
                  }
              }
          }
  
          public BluetoothDevice getDevice(int position) {
              return mLeDevices.get(position);
          }
  
          public void clear() {
              mLeDevices.clear();
          }
  
          @Override
          public int getCount() {
              return mLeDevices.size();
          }
  
          @Override
          public Object getItem(int i) {
              return mLeDevices.get(i);
          }
  
          @Override
          public long getItemId(int i) {
              return i;
          }
  
          @Override
          public View getView(int i, View view, ViewGroup viewGroup) {
              ViewHolder viewHolder;
              // General ListView optimization code.
              if (view == null) {
                  view = mInflator.inflate(R.layout.listitem_device, null);
                  viewHolder = new ViewHolder();
                  viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
                  viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
                  view.setTag(viewHolder);
              } else {
                  viewHolder = (ViewHolder) view.getTag();
              }
  
              BluetoothDevice device = mLeDevices.get(i);
              final String deviceName = device.getName();
              if (deviceName != null &amp;&amp; deviceName.length() &gt; 0)
                  viewHolder.deviceName.setText(deviceName);
              else
                  viewHolder.deviceName.setText(R.string.unknown_device);
              viewHolder.deviceAddress.setText(device.getAddress());
  
              return view;
          }
      }
  
      // Device scan callback.
      private BluetoothAdapter.LeScanCallback mLeScanCallback =
              new BluetoothAdapter.LeScanCallback() {
  
          @Override
          public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
              runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                      mLeDeviceListAdapter.addDevice(device);
                      mLeDeviceListAdapter.notifyDataSetChanged();
                  }
              });
          }
      };
  
      static class ViewHolder {
          TextView deviceName;
          TextView deviceAddress;
      }
  }
  </code></pre>
  
  <p><strong>Current Information:</strong></p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/21237093/android-4-3-how-to-connect-to-multiple-bluetooth-low-energy-devices">Android 4.3: How to connect to multiple Bluetooth Low Energy devices</a></li>
  <li><a href="https://developer.android.com/guide/topics/connectivity/bluetooth-le.html" rel="nofollow noreferrer">https://developer.android.com/guide/topics/connectivity/bluetooth-le.html</a></li>
  <li><a href="https://stackoverflow.com/questions/18327815/does-andriod-4-3-support-multiple-ble-device-connections">Does Android 4.3 support multiple BLE device connections?</a></li>
  <li><a href="https://stackoverflow.com/questions/20214862/ble-multiple-connection">Ble multiple connection</a></li>
  <li><a href="https://labs.hybris.com/2014/10/06/connecting-to-multiple-ble-devices/" rel="nofollow noreferrer">https://labs.hybris.com/2014/10/06/connecting-to-multiple-ble-devices/</a></li>
  <li><a href="https://e2e.ti.com/support/wireless_connectivity/f/538/t/225935" rel="nofollow noreferrer">https://e2e.ti.com/support/wireless_connectivity/f/538/t/225935</a></li>
  </ul>
  
  <p>All of these pages contain some directions, but they do not provide enough detail on how multiple connections can be implemented.</p>
  
  <p><strong>UI Target Representation:</strong></p>
  
  <p><img src="https://i.stack.imgur.com/RLhms.jpg" alt="Diagram"></p>
  
  <p>The idea is that my 5.1.1 Android Nexus 7 device will be able to connect to at most 5 BLE chip slaves and send/receive updates.</p>