2015-10-15 163 views
6

我升级到Android 6,我的使用蓝牙的应用程序无法使用这个新的API版本。这与Play Store上的应用程序存在同样的问题:蓝牙spp工具专业版(查看蓝牙是否有效的良好应用程序),它不会发现设备。Android 6蓝牙

这个问题似乎是在蓝牙发现:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
mBluetoothAdapter.startDiscovery() 
Log.i("BLUETOOTH", String.valueOf(mBluetoothAdapter.isDiscovering())); // Return false 

我的应用程序与Android 4/5运作良好,我也跟着:http://developer.android.com/guide/topics/connectivity/bluetooth.html

+0

哪些设备遇到此问题?哪个连结?我使用Nexus 5 –

+0

这是一个联系5 – eldina

回答

18

与Android 6.0盯着它是不足以包含清单的权限。 您必须明确询问用户每个被认为“危险”的权限。 BluetoothDevice.ACTION_FOUND需要蓝牙以及ACCESS_COARSE_LOCATION权限 http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND

的ACCESS_COARSE_LOCATION http://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION 是一个“危险”的许可,因此,你要问使用做实际的发现之前它requestPermission了。

public void doDiscovery() { 
    int hasPermission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION); 
    if (hasPermission == PackageManager.PERMISSION_GRANTED) { 
     continueDoDiscovery(); 
     return; 
    } 

    ActivityCompat.requestPermissions(MainActivity.this, 
      new String[]{ 
        android.Manifest.permission.ACCESS_COARSE_LOCATION}, 
      REQUEST_COARSE_LOCATION_PERMISSIONS); 
} 

然后你会得到用户的答案上onRequestPermissionsResult

@Override 
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { 
    switch (requestCode) { 
     case REQUEST_COARSE_LOCATION_PERMISSIONS: { 
      if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       continueDoDiscovery(); 
      } else { 
       Toast.makeText(this, 
         getResources().getString(R.string.permission_failure), 
         Toast.LENGTH_LONG).show(); 
       cancelOperation(); 
      } 
      return; 
     } 
    } 
} 

要使用的机器人,你应该使用兼容库,并使用ActivityCompat

+0

这是Bluetooth的必要吗?或只为acess_coarse_location? –

+0

是的,对于这两个,根据谷歌文档,https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND – Luci

3

我花了一些时间来调查这个问题。
在Android bug跟踪器上创建bug报告here
问题是系统不会将BluetoothDevice.ACTION_FOUND意向转发到注册BroadcastReceiver。 logcat中这样表示线路:

10-16 07:34:09.147  786-802/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } to ProcessRecord{5ce2d92 21736:com.example.mvl.bluetoothtest/u0a74} (pid=21736, uid=10074) requires android.permission.ACCESS_COARSE_LOCATION due to sender com.android.bluetooth (uid 1002)  

这对我的主题,应用程序需要android.permission.ACCESS_COARSE_LOCATION权限收到此意图。我个人不明白为什么我需要这个许可来获得蓝牙设备。
所以,如果添加此权限您的清单,那么就应该有一个更加前提工作 - 你必须设定目标SDK,并与SDK不高于编译,然后22

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
+0

ACCESS_COARSE_LOCATION是必需的,因为蓝牙(如Wi-Fi和网络(严格来说不是GPS设备))也可以帮助您指定使用BT信标的位置。因此授予位置权限也是预先要求的。 – dekaru

0

在检查的来源进行调用以前的版本工作代码在GattService.java中,你会发现一些代码评论 in方法onScanResult:

// Do no report if location mode is OFF or the client has no location permission 
// PEERS_MAC_ADDRESS permission holders always get results 
if (hasScanResultPermission(client) && matchesFilters(client, result)) { 
    try { 
     ScanSettings settings = client.settings; 
     if ((settings.getCallbackType() & 
           ScanSettings.CALLBACK_TYPE_ALL_MATCHES) != 0) { 
      app.callback.onScanResult(result); 
     } 
    } catch (RemoteException e) { 
     Log.e(TAG, "Exception: " + e); 
     mClientMap.remove(client.clientIf); 
     mScanManager.stopScan(client); 
    } 
} 

这说明了获取蓝牙LE广告报告需要什么。