码:

我使用来自here的以下代码,目标API级别为23(最低API级别为18)。

private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
    public void onReceive(Context context, Intent intent)
    {
        String action = intent.getAction();

        if (BluetoothDevice.ACTION_FOUND.equals(action))
        {
            bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            deviceNameTextView.setText(bluetoothDevice.getName());
        }
    }
};


在按下按钮的事件中,我称:

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery(); // was initialized successsfully


我的AndroidManifest.xml包含:

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


设备:


三星Galaxy S III(API级别18)
索尼Xperia Z3(API级别23)


事实:


两种设备都运行完全相同的代码
设备1可以发现设备2(以及任何其他蓝牙设备)
设备2无法发现设备1(或任何其他蓝牙设备)
两种设备都是可发现的
使用标准系统对话框对可发现性进行了测试,以成功将两个设备配对
这两个设备一直都未配对(我不想配对)
没有异常被抛出。


怎么了?

更新1:
由于API级别23,可能必须在运行时请求权限。伊薇特指出了这一点,谢谢!不幸的是它没有解决我的问题。

反对她的理论的是:

mBluetoothAdapter.startDiscovery()返回true,表示成功(请参见here)。

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity , Manifest.permission.BLUETOOTH_ADMIN);

if(permissionCheck == PackageManager.PERMISSION_GRANTED)
    Log.i("info", "Permission granted!");
else
    Log.i("info", "Permission not granted!");


使用BLUETOOTH_ADMINBLUETOOTH运行此代码将返回两次:


  许可授予!

最佳答案

在进行一些研究时,我从官方文档中找到了关于Android 6.0(API级别23)更改的following article


  通过访问附近的外部设备的硬件标识符
  蓝牙和Wi-Fi扫描,您的应用现在必须具有
  ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限:
  -WifiManager.getScanResults()
  -BluetoothDevice.ACTION_FOUND
  -BluetoothLeScanner.startScan()


因此,我一直都缺少权限ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION。但是仅将它们添加到AndroidManifest.xml文件中是不够的。您必须在运行时像Yvette建议的那样请求这些特权。

您可以找到here如何做到这一点,或者只是使用我编写的这段代码来获取蓝牙发现所需的权限。

final int CODE = 5; // app defined constant used for onRequestPermissionsResult

String[] permissionsToRequest =
{
    Manifest.permission.BLUETOOTH_ADMIN,
    Manifest.permission.BLUETOOTH,
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
};

boolean allPermissionsGranted = true;

for(String permission : permissionsToRequest)
{
    allPermissionsGranted = allPermissionsGranted && (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
}

if(!allPermissionsGranted)
{
    ActivityCompat.requestPermissions(this, permissionsToRequest, CODE);
}

mBluetoothAdapter.startDiscovery();


此代码假定用户授予了权限(为简单起见)。如果希望您的应用在未授予权限时表现不同,请参阅此article中的“处理权限请求响应”。

08-18 11:20
查看更多