bluetooth lowenergy - BLE scan result.getDevice().getName() is always null with Android 8 - Stack Overflow

I'm making an Android app for BLE communication with a physical device.Target SDK version is 32 -

I'm making an Android app for BLE communication with a physical device.

Target SDK version is 32 - Min SDK version is 23

The first phase is obviously scanning for advertising devices.

In short, the problem is that the result returned in ScanResult never contains the deviceName in Android 8, but it is always null. It works fine with Android 6, 10, and 12.

I checked the official documentation and various examples and I seem to be doing everything in the right way. I'm stuck in this situation and I hope someone notices something strange in my code.

I have a BluetoothLeScanner object on which I perform the scan method inside an Activity.

The following method is called when a Button is pressed:

@SuppressLint("MissingPermission")
private void doBleScan() {

    ScanSettings scanSettings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .build();

    ArrayList<ScanFilter> filters = new ArrayList<>();
    
    mDiscoveredDevices = new HashSet<>();
    mBluetoothLeScanner.startScan(filters, scanSettings, scanCallback);
}

The instantiated ScanCallback object has its own onScanResult method:

@Override
@SuppressLint("MissingPermission")
public void onScanResult(int callbackType, ScanResult result) {
    super.onScanResult(callbackType, result);

    //always null with Android 8
    String deviceName = result.getDevice().getName();

    if(deviceName != null) {
        txtLog.append("\nDN" + deviceName);
        mDiscoveredDevices.add(result.getDevice());
    }
}

The manifest file contains many declarations. The project is quite complex and also requires access to Wi-Fi networks, GPS location and tablet memory:

<uses-feature android:name="android.hardware.location.gps" />
<uses-feature
    android:name="android.hardware.bluetooth_le"
    android:required="true" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
    android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation"
    tools:targetApi="s" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

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

Of course, before scanning, I perform a runtime permission check.

With Build.VERSION.SDK_INT >= Build.VERSION_CODES.S I check Manifest.permission.BLUETOOTH_SCAN and Manifest.permission.BLUETOOTH_CONNECT permissions.

Otherwise I check only Manifest.permission.ACCESS_FINE_LOCATION permission.

private void requestRelevantRuntimePermissions() {
    String title;
    String message;
    String[] permissions;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        title = "Bluetooth permissions required";
        message = "Starting from Android 12, the system requires apps to be granted " +
                "Bluetooth access in order to scan for and connect to BLE devices.";
        permissions = new String[]{Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_CONNECT};
    } else {
        title = "Location permission required";
        message = "Starting from Android M (6.0), the system requires apps to be granted " +
                "location access in order to scan for BLE devices.";
        permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
    }
    requestPermissions(title, message, permissions);
}

private void requestPermissions(final String title, final String message, final String[] permissions) {

    final Activity activity = this;
    mPermissionToCheck = permissions;

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);

            alertDialogBuilder
                    .setTitle(title)
                    .setMessage(message)
                    .setCancelable(false)
                    .setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            ActivityCompat.requestPermissions(
                                    activity,
                                    permissions,
                                    RUNTIME_PERMISSION_REQUEST
                            );
                        }
                    });

            AlertDialog alertDialog = alertDialogBuilder.create();
            alertDialog.show();
        }
    });
}

I have the impression that there is some permission not requested or badly requested but honestly I can not identify the problem.

Any suggestions?

Thanks in advance to those who will try to help me

I'm making an Android app for BLE communication with a physical device.

Target SDK version is 32 - Min SDK version is 23

The first phase is obviously scanning for advertising devices.

In short, the problem is that the result returned in ScanResult never contains the deviceName in Android 8, but it is always null. It works fine with Android 6, 10, and 12.

I checked the official documentation and various examples and I seem to be doing everything in the right way. I'm stuck in this situation and I hope someone notices something strange in my code.

I have a BluetoothLeScanner object on which I perform the scan method inside an Activity.

The following method is called when a Button is pressed:

@SuppressLint("MissingPermission")
private void doBleScan() {

    ScanSettings scanSettings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .build();

    ArrayList<ScanFilter> filters = new ArrayList<>();
    
    mDiscoveredDevices = new HashSet<>();
    mBluetoothLeScanner.startScan(filters, scanSettings, scanCallback);
}

The instantiated ScanCallback object has its own onScanResult method:

@Override
@SuppressLint("MissingPermission")
public void onScanResult(int callbackType, ScanResult result) {
    super.onScanResult(callbackType, result);

    //always null with Android 8
    String deviceName = result.getDevice().getName();

    if(deviceName != null) {
        txtLog.append("\nDN" + deviceName);
        mDiscoveredDevices.add(result.getDevice());
    }
}

The manifest file contains many declarations. The project is quite complex and also requires access to Wi-Fi networks, GPS location and tablet memory:

<uses-feature android:name="android.hardware.location.gps" />
<uses-feature
    android:name="android.hardware.bluetooth_le"
    android:required="true" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
    android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation"
    tools:targetApi="s" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

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

Of course, before scanning, I perform a runtime permission check.

With Build.VERSION.SDK_INT >= Build.VERSION_CODES.S I check Manifest.permission.BLUETOOTH_SCAN and Manifest.permission.BLUETOOTH_CONNECT permissions.

Otherwise I check only Manifest.permission.ACCESS_FINE_LOCATION permission.

private void requestRelevantRuntimePermissions() {
    String title;
    String message;
    String[] permissions;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        title = "Bluetooth permissions required";
        message = "Starting from Android 12, the system requires apps to be granted " +
                "Bluetooth access in order to scan for and connect to BLE devices.";
        permissions = new String[]{Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_CONNECT};
    } else {
        title = "Location permission required";
        message = "Starting from Android M (6.0), the system requires apps to be granted " +
                "location access in order to scan for BLE devices.";
        permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
    }
    requestPermissions(title, message, permissions);
}

private void requestPermissions(final String title, final String message, final String[] permissions) {

    final Activity activity = this;
    mPermissionToCheck = permissions;

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);

            alertDialogBuilder
                    .setTitle(title)
                    .setMessage(message)
                    .setCancelable(false)
                    .setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            ActivityCompat.requestPermissions(
                                    activity,
                                    permissions,
                                    RUNTIME_PERMISSION_REQUEST
                            );
                        }
                    });

            AlertDialog alertDialog = alertDialogBuilder.create();
            alertDialog.show();
        }
    });
}

I have the impression that there is some permission not requested or badly requested but honestly I can not identify the problem.

Any suggestions?

Thanks in advance to those who will try to help me

Share Improve this question asked Mar 4 at 11:21 LipsyorLipsyor 4481 gold badge7 silver badges21 bronze badges 2
  • Does result.getScanRecord().getDeviceName() also return null ? – Michael Commented Mar 5 at 9:57
  • @Michael, same result. It seems to be null with all devices – Lipsyor Commented Mar 5 at 11:02
Add a comment  | 

1 Answer 1

Reset to default 0

If you are only interested in the name that is present in the advertisement message, you should not use the getDevice() method since that returns the system's device object which is a representation of the remote device, whose device name might or might not be the same value as in the advertisement packet.

Instead, you should use getScanRecord(). If this is non-null, you can inspect the name in the scan record using the getDeviceName() method. If the name was not present in the scan record, it will be null.

You can inspect the HCI log or use a BLE sniffer to see the raw advertisement. You can also use the getBytes() method to see the raw packet. If you don't get the name, I suggest you to inspect those bytes to see what's wrong. You could also use the app nRF Connect to inspect the bytes.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745047243a4608174.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信