问题
I have an app using bluetooth and connecting to devices, can'f find any devices using BluetoothAdapter.getDefaultAdapter().startDiscovery(); It worked fine just before discovery. Tried also other apps, it doesn't work in other apps as well. But the device I try to pair (Arduino bt-module) can be found in Android settings. Any idea what could I try? I implemented everything like described on http://developer.android.com/guide/topics/connectivity/bluetooth.html and it worked before the update.
回答1:
Bluetooth Adapter has been change in Android 6.0
You need to set the permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission and need to use BluetoothLeScanner.startScan() method to start the scan.
Below is the description from change logs:
To provide users with greater data protection, in Android 6.0, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:
WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address.
You can get more details from this link : http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html
回答2:
Just enable Location in Settings and it works well !!
回答3:
From API level 23, location access permission (ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION ) is also needed for bluetooth discovery.
https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id
And just adding permission into manifest file is not sufficient as the permission belongs to "dangerous" protection level. User consent is needed to request the permission at runtime.
Added permission into AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
Request for ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION at run time:
private void accessLocationPermission() {
int accessCoarseLocation = checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION);
int accessFineLocation = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listRequestPermission = new ArrayList<String>();
if (accessCoarseLocation != PackageManager.PERMISSION_GRANTED) {
listRequestPermission.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (accessFineLocation != PackageManager.PERMISSION_GRANTED) {
listRequestPermission.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
}
if (!listRequestPermission.isEmpty()) {
String[] strRequestPermission = listRequestPermission.toArray(new String[listRequestPermission.size()]);
requestPermissions(strRequestPermission, REQUEST_CODE_LOC);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_LOC:
if (grantResults.length > 0) {
for (int gr : grantResults) {
// Check if request is granted or not
if (gr != PackageManager.PERMISSION_GRANTED) {
return;
}
}
//TODO - Add your code here to start Discovery
}
break;
default:
return;
}
}
More details about permission: https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en
来源:https://stackoverflow.com/questions/33052811/since-marshmallow-update-bluetooth-discovery-using-bluetoothadapter-getdefaultad