#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 показывает, что необходимо установить разрешения во время выполнения. Я тоже пробовал это, но безрезультатно.