BLE запускает обратный вызов, который не вызывается на Android

#java #android #android-studio #bluetooth-lowenergy

#Ява #Android #android-студия #bluetooth-низкое энергопотребление

Вопрос:

Я пытаюсь считывать данные с устройства BLE в Android. Код довольно стандартный. Но по какой-то причине callback функция вообще не вызывается.

В моем AndroidManifest.xml , я добавил следующие разрешения

 lt;uses-permission android:name="android.permission.BLUETOOTH_SCAN" /gt; lt;uses-permission android:name="android.permission.BLUETOOTH" /gt; lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /gt; lt;uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /gt; lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /gt; lt;uses-permission android:name="android.permission.INTERNET" /gt; lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /gt; lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /gt;  

Это выглядит следующим MainActivity.java образом

 package com.example.blescandemo;  import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.Intent; import android.os.Bundle;  import com.google.android.material.snackbar.Snackbar;  import androidx.appcompat.app.AppCompatActivity;  import android.os.Handler; import android.os.ParcelUuid; import android.util.Log; import android.view.View;  import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI;  import com.example.blescandemo.databinding.ActivityMainBinding;  import java.util.ArrayList; import java.util.List; import java.util.UUID;  public class MainActivity extends AppCompatActivity {   private AppBarConfiguration appBarConfiguration;  private ActivityMainBinding binding;  private BluetoothAdapter bluetoothAdapter; private BluetoothLeScanner bluetoothLeScanner;  private ScanSettings settings; private Listlt;ScanFiltergt; filters; private ScanCallback callback;  private static final String LOG_TAG = "BLEDEMO"; private static final String UUID_STR = "lt;MY_UUIDgt;";  private boolean isScanning = false;  @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);   binding = ActivityMainBinding.inflate(getLayoutInflater());  setContentView(binding.getRoot());   setSupportActionBar(binding.toolbar);   NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);  appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();  NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);   binding.fab.setOnClickListener(new View.OnClickListener() {  @Override  public void onClick(View view) {  Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)  .setAction("Action", null).show();  }  });  initBLEScan();  startScanning(); }  private void startScanning() {  final int SCAN_DUR = 20000;  if(!isScanning) {  Handler handler = new Handler();  handler.postDelayed(new Runnable() {  @Override  public void run() {  isScanning = false;  bluetoothLeScanner.stopScan(callback);  Log.i(LOG_TAG, "[run] BLE Scanning stopped");  }  }, SCAN_DUR);   isScanning = true;  bluetoothLeScanner.startScan(filters, settings, callback);  Log.i(LOG_TAG, "BLE Scanning started");  } else {  isScanning = false;  bluetoothLeScanner.stopScan(callback);  Log.i(LOG_TAG, "BLE Scanning stopped");  } }  private void initBLEScan() {  Log.i(LOG_TAG, "Init BLE scan");  bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  if(bluetoothAdapter == null) {  Log.i(LOG_TAG, "No adapter found");  return;  }  enableBluetooth(this, bluetoothAdapter);  bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();  buildScanSettings();  buildScanFilters();  createScanCallback(); }  private void createScanCallback() {  callback = new ScanCallback() {  @Override  public void onScanResult(int callbackType, ScanResult result) {  super.onScanResult(callbackType, result);  String devName = result.getDevice().getName();  String devAddr = result.getDevice().getAddress();  Log.i(LOG_TAG, "Device name : "   devName   ", Address : "   devAddr);   ScanRecord rec = result.getScanRecord();  byte[] manufacturer = rec.getManufacturerSpecificData(224);  Log.i(LOG_TAG, "Manufacturer data : "   manufacturer);   int rssi = result.getRssi();  Log.i(LOG_TAG, "RSSI : "   rssi);  }   @Override  public void onScanFailed(int errorCode) {  super.onScanFailed(errorCode);  Log.e(LOG_TAG, "Scan failed with error : "   errorCode);  }  };  Log.i(LOG_TAG, "Scan Callback created"); }  private void buildScanFilters() {  filters = new ArrayListlt;ScanFiltergt;();  UUID uuid = UUID.fromString(UUID_STR);  UUID[] uuids = new UUID[]{uuid};  for(UUID t : uuids) {  ScanFilter filter = new ScanFilter  .Builder()  .setServiceUuid(new ParcelUuid(t))  .build();  filters.add(filter);  }  Log.i(LOG_TAG, "Scan Filter built"); }  private void buildScanSettings() {  ScanSettings.Builder builder = new ScanSettings.Builder();  builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);  settings = builder.build();  if (settings == null) {  Log.e(LOG_TAG, "Scan Settings null");  } else {  Log.i(LOG_TAG, "Scan settings built");  } } private void enableBluetooth(Activity activity, BluetoothAdapter bluetoothAdapter) {  if(!bluetoothAdapter.isEnabled()) {  Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  activity.startActivityForResult(intent, 1);  Log.i(LOG_TAG, "Enabling bluetooth");  } else {  Log.i(LOG_TAG, "Bluetooth Already enabled");  } } }  

Я предоставляю ScanCallback объект в методе startScan , но реализованные методы обратного вызова не вызываются. Я не совсем понимаю, почему это происходит. Быстрый поиск в Google показывает, что необходимо установить разрешения во время выполнения. Я тоже пробовал это, но безрезультатно.