13

Я пытаюсь использовать функцию BluatoothLeScanner.startScan вместо устаревшего одного BluetoothAdapter.startLeScan. Вчера я обновил свой Nexus 5 до Android 6.0, и с этого момента мое приложение больше не работает. Прежде всего, необходимо указать необходимые параметры ACCESS_COARSE_LOCATION как найдено здесь, https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id. Затем я добавил разрешение, как описано здесь: https://developer.android.com/training/permissions/requesting.html. Но в конце кажется, что он не работает, он не отправляет обратно устройства.BluetoothLeScanner.startScan с Android 6.0 не обнаруживает устройства

Это мой код:

манифеста

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
      package="com.stm.sensitronapp"> 
      <uses-sdk android:maxSdkVersion="23"/> 
      <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> 

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

DeviceScanActivity

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
... 

if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) 
      != PackageManager.PERMISSION_GRANTED){ 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, 
       Manifest.permission.ACCESS_COARSE_LOCATION)) { 
     } else { 
      ActivityCompat.requestPermissions(this, 
        new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 
        MY_PERMISSIONS_REQUEST_ACCESS_COARSE); 
     } 
    } 

// Device scan callback. 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) 
       == PackageManager.PERMISSION_GRANTED) { 
      mScanCallback = new ScanCallback() { 
       @Override 
       public void onScanResult(int callbackType, ScanResult result) { 
        super.onScanResult(callbackType, result); 
        mLeDeviceListAdapter.addDevice(result.getDevice()); 
        mLeDeviceListAdapter.notifyDataSetChanged(); 
       } 
      }; 
     } 
    } 
} 
final BluetoothManager bluetoothManager = 
      (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
mBluetoothAdapter = bluetoothManager.getAdapter(); 

if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { 
     mSwipeRefreshLayout.setRefreshing(true); 
     mLeDeviceListAdapter.clear(); 
     mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); 
     if(ContextCompat.checkSelfPermission(this, 
        Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 
       mBluetoothLeScanner.startScan(mScanCallback); 
      } 
     } 

EDIT: чтобы решить эту проблему, я только включил GPS. Это легко сделать программно в this way.

+0

У меня такая же проблема. Вы нашли какие-нибудь обходные пути? Я подумываю попробовать новое сканирование api, но больно поддерживать совместимость между ними, поскольку они работают по-разному. –

+4

Да, посмотрите здесь, есть решение: [Bluetooth Low Energy startScan на Android 6.0 не находит устройства] (http://stackoverflow.com/questions/33043582/bluetooth-low-energy-startscan-on-android-6 -0-does-not-find-devices) Однако решение: добавить разрешения в манифест, добавить разрешения в runTime в действие с помощью ScanDevice, включить GPS. Невероятно думать, но моя проблема была в отключенном GPS –

+1

Я только что протестировал его с включенным GPS, и это сработало (я был на планшете, который его отключил). Это безумие, что мы должны включить GPS, чтобы отсканировать BLE, что, если устройство даже не имеет в нем чипа GPS? Ошибка должна быть немедленно отправлена. Я бы подумал, что парни-парни и другие, которые делают BLE-устройства для масс, уже попали бы в Google с этими вопросами. –

ответ

14

если предоставлены разрешения, попробуйте включить GPS.

+0

Но почему так? Я только обращаюсь к Bluetooth? P.S: ваше решение действительно работает –

+1

Изменения Android 6.0: чтобы предоставить пользователям более полную защиту данных, начиная с этой версии, Android удаляет программный доступ к локальному идентификатору оборудования для приложений с использованием API Wi-Fi и Bluetooth. – qinmiao

+0

Ты сделал мой день! – hoangtu23

5

Это приложение, запрашивающее разрешение на размещение при запуске? Если это не так, обработайте код в другом месте, чтобы он запрашивался.

Также вы можете проверить это, чтобы проверить, если ваше приложение работает нормально:

Открыть Настройки> Приложения> YourApplication> Разрешение и включить Место и попытаться просканировать результаты.

Местоположение будет указано в списке разрешений, только если вы предоставили ACCESS_COARSE_LOCATION в манифесте.

+1

Я добавил разрешения на размещение, но он не работает. Он запускает сканирование, но он ничего не отвечает в обратном вызове. –

+0

Я добавил «штраф» и «грубые» разрешения, но все равно не повезло. обратный вызов обнаружения не запускается. Marshmallow on Nexus 9. Я проверил Местоположение разрешено в настройках Android для приложения. Я вижу, что устройство найдено, но обратный вызов не запускается. Также я могу проверить, что он уволен на Lollipop. Любое решение? – 4ntoine

+2

Я могу это подтвердить. После добавления ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION в Манифест И включение местоположения в телефоне работает проверка BLE. Я тестировал его на Nexus 6 с Android 6.0, и он работает. –

0

Один - не идеальный ответ, так это то, что вы все равно можете использовать один и тот же метод BT-сканирования старого метода, как только у вас будет разрешено разрешение на размещение в новом режиме.

  mBluetoothAdapter.startDiscovery(); 

.......

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

       if (BluetoothDevice.ACTION_FOUND.equals(action)) { 
       BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 

       mDeviceList.add(device); 


      } 
     } 
    }; 
+1

Это классическое Bluetooth-сканирование. OP говорит о сканировании LE. – Mackovich

+1

Прошу прощения, если у вас сложилось неправильное впечатление. Я просто указываю, что нет абсолютно никакой связи между Bluetooth Classic Discovery и Bluetooth Low Energy Scan. Эти два сканирования совершенно разные. Первое сканирование никогда не будет возвращать устройства BLE, если нет двойного режима и не обнаруживается. И, наконец, вам не нужно разрешение на размещение и включено для Classic Bluetooth Discovery (просто попробовал это сегодня). – Mackovich

+0

Но «классический» поиск устройств в стандартных настройках также проверяет устройства BTLE. Таким образом, он обнаруживает как классические, так и BTLE-устройства. Нижняя сторона состоит в том, что единственным следующим шагом, который можно предпринять, является соединение с устройством. Таким образом, невозможно подключиться к устройствам BTLE, которые не используют пары, используя этот подход. –

2

Используя решения приведенных выше работ, но побочным эффектом является то, что вы должны иметь место службы включен на то, что не нужно. Некрасиво и неудовлетворителен Обходной указать целевую версию в манифесте, чтобы

андроид: targetSdkVersion = «21»

Это позволяет сканировать на моем Nexus 7, даже если установленная версия 6.0.1. Я не знаю, какие побочные эффекты нацелены на более низкую версию, чем на установленную версию, но, по крайней мере, сканирование работает. Может быть единственным решением для устройств без GPS (если такие устройства существуют).

Google должен быть распят за это.

0

Это старый вопрос, но я отвечу, чтобы помочь кому-то.
К сожалению, комбинация ACCESS_COARSE_LOCATION и targetSdkVersion 22 не работает на некоторых устройствах.
Это не хороший метод, но я решил его следующим образом без использования разрешений во время выполнения (ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION)

  1. Установите ваш «targetSdkVersion» до 19 (я думаю, что, может быть, api19 ~ api22 будет возможно)
  2. Добавьте следующее разрешение вашего файла манифеста

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

протестированы на Android 4.4 ~ 7.1.1

-2

Установите «minSdkVersion» на 18 targetSdkVersion 22

+0

это правильный ответ – Rest

Смежные вопросы