write things low example devices code ble android bluetooth-lowenergy android-bluetooth android-6.0-marshmallow

android - things - bluetooth le devices



Bluetooth LE Scan no funciona en Android M en segundo plano (3)

Añadir permiso de ubicación junto con BLE

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

Copiar Pegar este método para solicitar y otorgar permiso de ubicación

@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: { Map<String, Integer> perms = new HashMap<String, Integer>(); // Initial perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED); // Fill with results for (int i = 0; i < permissions.length; i++) perms.put(permissions[i], grantResults[i]); // Check for ACCESS_FINE_LOCATION if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) { // All Permissions Granted // Permission Denied Toast.makeText(ScanningActivity.this, "All Permission GRANTED !! Thank You :)", Toast.LENGTH_SHORT) .show(); } else { // Permission Denied Toast.makeText(ScanningActivity.this, "One or More Permissions are DENIED Exiting App :(", Toast.LENGTH_SHORT) .show(); finish(); } } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @TargetApi(Build.VERSION_CODES.M) private void fuckMarshMallow() { List<String> permissionsNeeded = new ArrayList<String>(); final List<String> permissionsList = new ArrayList<String>(); if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION)) permissionsNeeded.add("Show Location"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "App need access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return; } Toast.makeText(ScanningActivity.this, "No new Permission Required- Launching App .You are Awesome!!", Toast.LENGTH_SHORT) .show(); } private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(ScanningActivity.this) .setMessage(message) .setPositiveButton("OK", okListener) .setNegativeButton("Cancel", null) .create() .show(); } @TargetApi(Build.VERSION_CODES.M) private boolean addPermission(List<String> permissionsList, String permission) { if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); // Check for Rationale Option if (!shouldShowRequestPermissionRationale(permission)) return false; } return true; }

Y luego en onCreate verifica el permiso

if (Build.VERSION.SDK_INT >= 23) { // Marshmallow+ Permission APIs fuckMarshMallow(); }

Espero que ahorre su tiempo.

El siguiente código funciona muy bien en mi Nexus 9 con Android 5.1.1 (Build LMY48M), pero no funciona en un Nexus 9 con Android 6.0 (Build MPA44l)

List<ScanFilter> filters = new ArrayList<ScanFilter>(); ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)).build(); ScanFilter.Builder builder = new ScanFilter.Builder(); builder.setManufacturerData((int) 0x0118, new byte[]{(byte) 0xbe, (byte) 0xac}, new byte[]{(byte) 0xff, (byte)0xff}); ScanFilter scanFilter = builder.build(); filters.add(scanFilter); mBluetoothLeScanner.startScan(filters, settings, new ScanCallback() { ... });

En Android 5.x, el código anterior produce una devolución de llamada cuando se ve un anuncio del fabricante que coincide con el filtro de escaneo. (Vea el ejemplo de salida Logcat a continuación). En el Nexus 9 con MPA44l, no se reciben devoluciones de llamada. Si comenta el filtro de exploración, las devoluciones de llamada se reciben correctamente en el Nexus 9.

09-22 00:07:28.050 1748-1796/org.altbeacon.beaconreference D/BluetoothLeScanner﹕ onScanResult() - ScanResult{mDevice=00:07:80:03:89:8C, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={280=[-66, -84, 47, 35, 68, 84, -49, 109, 74, 15, -83, -14, -12, -111, 27, -87, -1, -90, 0, 1, 0, 1, -66, 0]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-64, mTimestampNanos=61272522487278}

¿Alguien ha visto a ScanFilters funcionar en Android M?


El problema no era el filtro de escaneo, sino que el filtro de escaneo solo se usaba cuando la aplicación estaba en segundo plano. A partir de Android M, el escaneo de Bluetooth LE en segundo plano se bloquea a menos que la aplicación tenga uno de los dos permisos siguientes:

android.permission.ACCESS_COARSE_LOCATION android.permission.ACCESS_FINE_LOCATION

La aplicación que estaba probando no solicitó ninguno de estos permisos, por lo que no funcionó en segundo plano (la única vez que el filtro de escaneo estaba activo) en Android M. Al agregar el primero se resolvió el problema.

Me di cuenta de que este era el problema porque vi la siguiente línea en Logcat:

09-22 22:35:20.152 5158 5254 E BluetoothUtils: Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results

Consulte aquí para obtener más información: https://code.google.com/p/android-developer-preview/issues/detail?id=2964


Tuve un problema similar con una aplicación que se conecta a bluetooth. No LE ScanFilter, pero era un problema de permisos al igual que el OP tenía.

La causa principal es que a partir del SDK 23, debe solicitar al usuario los permisos en tiempo de ejecución utilizando el método requestPermissions() .

Esto es lo que funcionó para mí:

  1. Agregue una de las siguientes dos líneas a AndroidManifest.xml , dentro del nodo raíz:

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

  2. En su Actividad, antes de intentar conectarse a bluetooth, llame al método requestPermissions() , que abre un cuadro de diálogo del sistema para solicitarle al usuario el permiso. El cuadro de diálogo de permisos se abre en un hilo diferente, así que asegúrese de esperar el resultado antes de intentar conectarse a Bluetooth.

  3. Reemplace la Activity de onRequestPermissionsResult() para manejar el resultado. Este método realmente solo necesitará hacer algo si el usuario se negó a otorgar el permiso, para decirle al usuario que la aplicación no puede hacer la actividad de bluetooth.

Esta publicación de blog tiene un código de ejemplo que utiliza AlertDialogs para decirle al usuario lo que está sucediendo. Es un buen punto de partida pero tiene algunas deficiencias:

  • No controla la espera para que requestPermissions() el requestPermissions()
  • El AlertDialog que envuelve la llamada a requestPermissions() parece extraño. Una requestPermissions() llamada a requestPermissions() es suficiente.