Obtaining list of connected bluetooth low energy d

2019-08-25 03:23发布

问题:

I'm working on application which shows list of certain connected bluetooth low energy devices, so user can choose which one of them he wants to configure.

The problem is that you can't just list all connected devices. As far as I know there are three possible ways:

  1. Use BluetoothProfiles

     bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    

    This fails because android won't connect to GATT server, when device connects, so device is neither under GATT_SERVER nor GATT profile. However once I call connectGatt method,

     bluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
    

    device can be found under both GATT_SERVER and GATT profile. Other profiles are not supported by low energy devices.

  2. List paired devices and try connectGatt on each of them

     List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
     for(BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
          BluetoothGatt gatt = device.connectGatt(getApplicationContext(), false, gattCallback);
          if(gatt != null) {
              connectedDevices.add(device);
          }
          gatt.disconnect();
     }
    

    This method cannot be used as it cannot determine if device is already connected or only in range but not connected

  3. On system boot start service listening to ACL_CONNECTED and ACL_DISCONNECTED intents and maintaining list of connected devices

    Manifest

     <service android:name=".ManagerService" android:enabled="true" />
     <receiver
        android:name=".BootFinishedReceiver"
        android:directBootAware="true"
        android:enabled="true"
        android:exported="false"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    

    Receiver

     public class BootFinishedReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
               Intent serviceIntent = new Intent(context, ManagerService.class);
               context.startService(serviceIntent);
          }
      }
    

    Service

     public class ManagerService extends Service {
          private static List<BluetoothDevice> connectedDevices;
    
          @Override
          public void onCreate() {
              connectedDevices = new ArrayList<BluetoothDevice>();
              super.onCreate();
          }
    
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
              IntentFilter filter = new IntentFilter();
              filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
              filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
              registerReceiver(connectionReceiver, filter);
              return super.onStartCommand(intent, flags, startId);
          }
    
          @Override
          public void onDestroy() {
              unregisterReceiver(connectionReceiver);
              super.onDestroy();
          }
    
          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
    
          private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  String action = intent.getAction();
                  BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                  if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                      connectedDevices.add(device);
                  }else{
                      connectedDevices.remove(device);
                  }
              }
          };
    
          public static List<BluetoothDevice> getConnectedDevices() {
              return connectedDevices;
          }
     }
    

    Since 3.1 apps can no longer receive system intents before activity is started, so this cannot be used either.

Is there any other way or how can I achieve it now in later android versions?

Thanks for any suggestions

回答1:

Well, I found out that you can still use ON_BOOT_COMPLETED, but you have to allow it in setting on your device. So my problem is solved