Bluetooth LE ScanFilters no funciona en Android M
El código siguiente funciona muy bien en mi Nexus 9 con Android 5.1.1 (Build LMY48M), pero no funcionará 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 de fabricante que coincide con el filtro de exploración. (Vea el ejemplo de salida de Logcat más abajo.) 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.
- 129 error y error 133 de Rxble durante la operación de lectura y escritura
- Android: El escáner Bluetooth Low Energy recibe datos nulos
- Creación de servicios de fondo para Bluetooth de baja energía en Android
- ¿Cómo usar LeDeviceListAdapter al intentar encontrar dispositivos BLE?
- Android 4.3 Bluetooth Baja energía inestable
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 ScanFilters trabajar en Android M?
- Android: BLE cómo leer múltiples características?
- Ble-obtener el código de error - 128 al escribir a caracteres
- Bluetooth GATT onConnectionState El cambio no funciona en Lollipop
- ¿Cómo obtener RSSI sin conexión al dispositivo BLE?
- Intervalo de tiempo de conexión BLE de Android
- Detectar dispositivos bluetooth Le en Android
- Reemplazo de startLeScan a api actual
- Vinculación mediante programación al dispositivo BLE en Android
Tuve un problema similar con una aplicación de conexión a bluetooth. No LE ScanFilter, pero era un problema de permisos igual que el OP.
La causa raíz es que a partir del SDK 23, debe solicitar al usuario permisos en tiempo de ejecución mediante el método requestPermissions()
.
Esto es lo que funcionó para mí:
-
Añada una de las dos líneas siguientes 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" />
-
En su actividad, antes de intentar conectarse al bluetooth, llame al método
requestPermissions()
, que abre un diálogo del sistema para solicitar al usuario el permiso. El diálogo de permisos se abre en un hilo diferente, así que asegúrese de esperar el resultado antes de intentar conectarse al bluetooth. -
onRequestPermissionsResult()
Activity
onRequestPermissionsResult()
para manejar el resultado. Este método realmente sólo tendrá que hacer algo si el usuario se negó a conceder el permiso, para decirle al usuario que la aplicación no puede hacer la actividad bluetooth.
Esta entrada del blog tiene algún código de ejemplo que utiliza AlertDialogs para decirle al usuario lo que está pasando. Es un buen punto de partida pero tiene algunas deficiencias:
- No controla la espera para que el
requestPermissions()
termine - El AlertDialog que envuelve la llamada a
requestPermissions()
parece extraño. UnarequestPermissions()
llamada arequestPermissions()
es suficiente.
El problema no era el filtro de escaneo, sino que el filtro de escaneado sólo se utilizaba cuando la aplicación estaba en segundo plano. A partir de Android M, la exploración Bluetooth LE en segundo plano está bloqueada a menos que la aplicación tenga uno de los siguientes dos permisos:
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. La adición de la primera solucionó 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
Consulta aquí para obtener más información: https://code.google.com/p/android-developer-preview/issues/detail?id=2964
Agregar 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 Pega este método para solicitar y conceder 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 cheque por permiso
if (Build.VERSION.SDK_INT >= 23) { // Marshmallow+ Permission APIs fuckMarshMallow(); }
Espero que ahorrar su tiempo.
- ColorDrawable no se puede convertir en android.support.v7.widget.RoundRectDrawableWithShadow
- No se carga el PDF de Android en el navegador y en WebView