8

We are trying to use CompanionDeviceManager class to pair our BLE device with our Android (Version 10) phone without need of location permission.

For testing purposes we activited bluetooth of multiple phones and ble devices around our test device.

We are using the example code from official site without success.

Added these codes to AndroidManifest file:

<uses-feature android:name="android.hardware.bluetooth"/>
<uses-feature android:name="android.software.companion_device_setup"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Complete code of MainActivity :

public class MainActivity extends AppCompatActivity {


    private CompanionDeviceManager deviceManager;
    private AssociationRequest pairingRequest;
    private BluetoothDeviceFilter deviceFilter;

    private static final int SELECT_DEVICE_REQUEST_CODE = 42;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("ArkSigner", "onCreate called.");

        deviceManager = getSystemService(CompanionDeviceManager.class);

        // To skip filtering based on name and supported feature flags (UUIDs),
        // don't include calls to setNamePattern() and addServiceUuid(),
        // respectively. This example uses Bluetooth.
        deviceFilter = new BluetoothDeviceFilter.Builder()
                //.setNamePattern(Pattern.compile("Test"))
                //.addServiceUuid(new ParcelUuid(new UUID(0x123abcL, -1L)), null)
                .build();

        // The argument provided in setSingleDevice() determines whether a single
        // device name or a list of device names is presented to the user as
        // pairing options.
        pairingRequest = new AssociationRequest.Builder()
                .addDeviceFilter(deviceFilter)
                //.setSingleDevice(true)
                .build();

        List<String> associations = deviceManager.getAssociations();

        // When the app tries to pair with the Bluetooth device, show the
        // appropriate pairing request dialog to the user.
        deviceManager.associate(pairingRequest,
                new CompanionDeviceManager.Callback() {
                    @Override
                    public void onDeviceFound(IntentSender chooserLauncher) {
                        try {

                            Log.e("ArkSigner", "onDeviceFound called.");

                            startIntentSenderForResult(chooserLauncher,
                                    SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0);
                        } catch (IntentSender.SendIntentException e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onFailure(CharSequence error) {
                        Log.e("ArkSigner", "onFailure called.");
                    }
                },
                null);


    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        
        Log.e("ArkSigner", "onActivityResult called.");

        if (requestCode == SELECT_DEVICE_REQUEST_CODE &&
                resultCode == Activity.RESULT_OK) {
            // User has chosen to pair with the Bluetooth device.
            BluetoothDevice deviceToPair =
                    data.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE);
            deviceToPair.createBond();

            // ... Continue interacting with the paired device.
        }
    }
}

After we run our Android application, we are not seeing any dialog about found devices.(Bluetooth or BLE devices)

Edit: If we give a devicename in line ".setNamePattern(Pattern.compile("Test"))" or use ".setSingleDevice(true)" it doesn't change anything.

Yunus Temurlenk
  • 4,085
  • 4
  • 18
  • 39
ArkSigner
  • 81
  • 1
  • 3

2 Answers2

6

You should use BluetoothLeDeviceFilter instead since BluetoothDeviceFilter is for non-BLE devices according to the documentation at https://developer.android.com/reference/android/companion/BluetoothDeviceFilter.

Also expect the parcelable extra to contain a android.bluetooth.le.ScanResult rather than a BluetoothDevice for BLE devices.

Emil
  • 16,784
  • 2
  • 41
  • 52
1

I had the same issue in Android 11. CompanionDeviceManager showed the Wi-Fi networks without an issue when I commented the ".addDeviceFilter(deviceFilter)" part. So, the issue was only with the Bluetooth devices.

To fix this issue, I just enabled "Location" and CompanionDeviceManager showed the Bluetooth devices as intended.

Also add this permission in the Manifest :

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

Reference : https://developer.android.com/guide/topics/connectivity/bluetooth

"Services running on Android 10 and higher cannot discover Bluetooth devices unless they have the ACCESS_BACKGROUND_LOCATION permission"

Prabath
  • 126
  • 5
  • 2
    Well that's strange. In this case it's not a service that scans. It's the device companion app (which is a system app) and hence you don't need any location permission for your own app. – Emil Mar 08 '21 at 16:58
  • 1
    The whole point of using Companion Device Manager is to avoid requiring location for BLE scanning. – Takeshi Kaga Sep 19 '21 at 05:23