扫描 BLE 设备后不调用 Android BLE 扫描回调 [英] Android BLE Scan Callback is not called after scanning for BLE devices
问题描述
我正在创建一个使用 Android Studio 扫描附近所有 BLE(低功耗蓝牙)设备的 Android 应用.
我想我已经实现了所有这些文档:
我认为这可能是因为未调用
BLE 扫描回调
(日志中没有 BLE 扫描回调).所以我的问题是我的代码有什么解决方案?我是否错过了编码?
这是我的代码
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android";包=com.example"><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";/><使用功能android:name="android.hardware.bluetooth_le";android:required="true"/><申请android:allowBackup="true";android:icon="@mipmap/ic_launcher";android:label="@string/app_name";android:roundIcon="@mipmap/ic_launcher_round";android:supportsRtl="true";android:theme="@style/Theme.Example"><activity android:name=".ui.authentication.signin.SignInActivity";/><activity android:name=".ui.authentication.signup.SignUpActivity"/><activity android:name=.ui.home.HomeActivity"><意图过滤器><action android:name="android.intent.action.MAIN";/><category android:name="android.intent.category.LAUNCHER";/></意图过滤器></活动></应用程序></清单>
BluetoothHelper.java:
package com.example.util;导入 android.Manifest;导入 android.app.Activity;导入 android.bluetooth.BluetoothAdapter;导入 android.bluetooth.BluetoothDevice;导入 android.bluetooth.le.BluetoothLeScanner;导入 android.bluetooth.le.ScanCallback;导入 android.bluetooth.le.ScanResult;导入 android.content.Context;导入 android.content.Intent;导入 android.content.pm.PackageManager;导入 android.os.Build;导入 android.os.Handler;导入 android.util.Log;导入 androidx.core.app.ActivityCompat;导入 androidx.core.content.ContextCompat;导入 java.util.ArrayList;导入 java.util.HashMap;导入 java.util.Set;公共类 BluetoothHelper {静态 int REQUEST_ENABLE_BT = 1;静态 int PERMISSION_CODE = 1;static String TAG =蓝牙";静态布尔 isScanning = false;//蓝牙权限来源:https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java//检查 Android 10 的蓝牙权限public static void android10BluetoothPermission(上下文上下文,活动活动){如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {如果(ContextCompat.checkSelfPermission(上下文,Manifest.permission.ACCESS_BACKGROUND_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(活动,新字符串[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},PERMISSION_CODE);}}}//设置蓝牙的来源:https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java//获取蓝牙适配器public static void setupBluetooth (BluetoothAdapter bluetoothAdapter) {如果(蓝牙适配器 == 空){Log.d(TAG,蓝牙:"+蓝牙适配器为空");}别的 {Log.d(TAG,蓝牙:"+蓝牙是适配器不为空");}}//启用蓝牙public static void enableBluetooth(活动活动,BluetoothAdapter bluetoothAdapter){Log.d(TAG, "蓝牙:"+"蓝牙适配器已启用:"+ bluetoothAdapter.isEnabled());如果 (!bluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);Log.d(TAG,蓝牙:"+蓝牙已启用");}别的 {Log.d(TAG,蓝牙:"+蓝牙已启用");}}//查找蓝牙设备的来源:https://developer.android.com/guide/topics/connectivity/bluetooth/find-bluetooth-devices//查询配对设备public static Set
查询配对设备(蓝牙适配器蓝牙适配器){设置<蓝牙设备>pairedDevices = bluetoothAdapter.getBondedDevices();Log.d(TAG, "PairedDevices: " + pairedDevices.toString());返回配对设备;}//获取所有名称和 MAC 地址公共静态 ArrayList >getNamesAndMacAddresses(Set bluetoothDevices) {ArrayList >arrayList = 新的 ArrayList<>();如果 (bluetoothDevices.size() > 0) {对于(蓝牙设备设备:蓝牙设备){String deviceName = device.getName();String deviceMacAddress = device.getAddress();HashMap<字符串,字符串>hashMap = new HashMap<>();hashMap.put("deviceName", deviceName);hashMap.put(deviceMacAddress", deviceMacAddress);arrayList.add(hashMap);}}Log.d(TAG, "NamesAndMacAddress: " + arrayList);返回数组列表;}//查找 BLE 设备的来源:https://developer.android.com/guide/topics/connectivity/bluetooth/find-ble-devices#java//扫描BLE设备public static void scanBLEDevices (BluetoothLeScanner bluetoothLeScanner) {int SCAN_DURATION = 10000;如果(!isScanning){Handler handler = new Handler();handler.postDelayed(new Runnable() {@覆盖公共无效运行(){isScanning = false;bluetoothLeScanner.stopScan(bleScanCallback);Log.d(TAG,ScanBLEDevices:"+停止扫描");}}, SCAN_DURATION);isScanning = true;bluetoothLeScanner.startScan(bleScanCallback);Log.d(TAG,ScanBLEDevices:"+开始扫描");}别的 {isScanning = false;bluetoothLeScanner.stopScan(bleScanCallback);Log.d(TAG,ScanBLEDevices:"+停止扫描");}}//BLE 扫描回调私有静态 ScanCallback bleScanCallback = 新 ScanCallback() {@覆盖public void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);Log.d(TAG, "ScanCallback: " + result.getDevice());}};} HomeActivity.java:
package com.example.ui.home;导入 androidx.appcompat.app.AppCompatActivity;导入 android.bluetooth.BluetoothAdapter;导入 android.bluetooth.BluetoothDevice;导入 android.bluetooth.le.BluetoothLeScanner;导入 android.os.Bundle;导入 android.view.View;导入 com.example.R;导入 com.example.databinding.ActivityHomeBinding;导入 com.example.util.AuthenticationHelper;导入 com.example.util.BluetoothHelper;导入 java.util.ArrayList;导入 java.util.HashMap;导入 java.util.Set;公共类 HomeActivity 扩展 AppCompatActivity 实现 View.OnClickListener {ActivityHomeBinding 绑定;设置<蓝牙设备>配对设备;ArrayList
>数组列表;BluetoothLeScanner bluetoothLeScanner;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);绑定 = ActivityHomeBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());设置蓝牙();binding.buttonKeluar.setOnClickListener(this);}@覆盖受保护的无效 onStart() {super.onStart();AuthenticationHelper.checkHasTheUserLoggedIn(this);}@覆盖public void onClick(View v) {if(v.getId() == R.id.buttonKeluar) {AuthenticationHelper.signOutUser(this);}}私有无效 setUpBluetooth() {BluetoothHelper.android10BluetoothPermission(this, HomeActivity.this);BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();BluetoothHelper.setupBluetooth(bluetoothAdapter);BluetoothHelper.enableBluetooth(this, bluetoothAdapter);pairedDevices = BluetoothHelper.queryPairedDevices(bluetoothAdapter);arrayList = BluetoothHelper.getNamesAndMacAddresses(pairedDevices);bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();BluetoothHelper.scanBLEDevices(bluetoothLeScanner);}} 更新
我将此代码添加到
BluetoothHelper.java
类中的android10BluetoothPermission()
函数中,但仍然无效.if (ContextCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(活动,新字符串[]{Manifest.permission.ACCESS_FINE_LOCATION},PERMISSION_CODE);}如果(ContextCompat.checkSelfPermission(上下文,Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(活动,新字符串[]{Manifest.permission.ACCESS_COARSE_LOCATION},PERMISSION_CODE);}
解决方案最后,我修改了我的代码,所以代码现在可以工作.这是:
ScanAndPairActivity.java(我正在创建一个用于扫描和配对 BLE 设备的新活动):
package com.example.ui.scanandpair;导入 androidx.annotation.NonNull;导入 androidx.appcompat.app.AppCompatActivity;导入 androidx.core.content.ContextCompat;导入 androidx.recyclerview.widget.LinearLayoutManager;导入 android.Manifest;导入 android.app.Activity;导入 android.app.AlertDialog;导入 android.bluetooth.BluetoothAdapter;导入 android.bluetooth.le.BluetoothLeScanner;导入 android.bluetooth.le.ScanCallback;导入 android.bluetooth.le.ScanFilter;导入 android.bluetooth.le.ScanResult;导入 android.bluetooth.le.ScanSettings;导入 android.content.DialogInterface;导入 android.content.Intent;导入 android.content.pm.PackageManager;导入 android.os.Build;导入 android.os.Bundle;导入 android.os.Handler;导入 android.util.Log;导入 android.view.View;导入 android.widget.Toast;导入 com.example.R;导入 com.example.databinding.ActivityScanAndPairBinding;导入 com.example.entity.BLEDeviceEntity;导入 java.util.ArrayList;导入 java.util.List;公共类 ScanAndPairActivity 扩展 AppCompatActivity {//一般的String TAG = getClass().getSimpleName();ActivityScanAndPairBinding 绑定;//蓝牙int REQUEST_ENABLE_BT = 1;布尔 isScanning = false;蓝牙适配器蓝牙适配器;BluetoothLeScanner bluetoothLeScanner;ScanAndPairAdapter scanAndPairAdapter;列表
bleDeviceEntityList;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);绑定 = ActivityScanAndPairBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());android10BluetoothPermission();scanAndPairAdapter = new ScanAndPairAdapter(this);bleDeviceEntityList = new ArrayList<>();}//蓝牙权限来源:https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java//检查 Android 10 的蓝牙权限私人无效android10BluetoothPermission(){boolean isLocationPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;boolean isBGLocationAccessNotGranted = false;如果 (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {isBGLocationAccessNotGranted = ContextCompat.checkSelfPermission(这,Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED;}boolean isLocationAccessNotGranted = ContextCompat.checkSelfPermission(这,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED;如果(isLocationPermissionRequired && isBGLocationAccessNotGranted && isLocationAccessNotGranted){requestLocationPermission();}别的 {设置蓝牙();}}私有无效 requestLocationPermission() {如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {如果(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)){AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);警报对话框构建器.setTitle(getString(R.string.izinkan_lokasi)).setMessage(getString(R.string.mohon_izinkan_aplikasi_mengakses_lokasi)).setPositiveButton(getString(R.string.ya), new DialogInterface.OnClickListener() {@覆盖public void onClick(DialogInterface dialog, int which) {makeLocationRequest();}});alertDialogBuilder.show();} 别的 {makeLocationRequest();}}}私有无效 makeLocationRequest() {如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {请求权限(新字符串[]{android.permission.ACCESS_FINE_LOCATION"},101);}}//请求许可结果@覆盖public void onRequestPermissionsResult(int requestCode, @NonNull String[] 权限, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);开关(请求代码){案例101:if (grantResults.length != 0 && grantResults[0] == 0) {设置蓝牙();}休息;默认:Toast.makeText(this, getString(R.string.maaf_izin_lokasi_harus_disetujui), Toast.LENGTH_LONG).show();}}私有无效 setUpBluetooth() {bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();检查蓝牙(蓝牙适配器);启用蓝牙(这个,蓝牙适配器);bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();scanBLEDevices(bluetoothLeScanner);}//设置蓝牙的来源:https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java//获取蓝牙适配器private void checkBluetooth (BluetoothAdapter bluetoothAdapter) {如果(蓝牙适配器 == 空){Log.d(TAG,蓝牙:"+蓝牙适配器为空");}别的 {Log.d(TAG,蓝牙:"+蓝牙是适配器不为空");}}//启用蓝牙private void enableBluetooth(活动活动,BluetoothAdapter bluetoothAdapter){Log.d(TAG, "蓝牙:"+"蓝牙适配器已启用:"+ bluetoothAdapter.isEnabled());如果 (!bluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);Log.d(TAG,蓝牙:"+蓝牙已启用");}别的 {Log.d(TAG,蓝牙:"+蓝牙已启用");}}//查找 BLE 设备的来源:https://developer.android.com/guide/topics/connectivity/bluetooth/find-ble-devices#java//扫描BLE设备private void scanBLEDevices (BluetoothLeScanner bluetoothLeScanner) {showProgressBar();int SCAN_DURATION = 5000;如果(!isScanning){Handler handler = new Handler();handler.postDelayed(new Runnable() {@覆盖公共无效运行(){isScanning = false;bluetoothLeScanner.stopScan(bleScanCallback);Log.d(TAG,ScanBLEDevices:"+停止扫描");populateDataToRecyclerView();}}, SCAN_DURATION);isScanning = true;showProgressBar();bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), bleScanCallback);Log.d(TAG,ScanBLEDevices:"+开始扫描");}别的 {isScanning = false;bluetoothLeScanner.stopScan(bleScanCallback);Log.d(TAG,ScanBLEDevices:"+停止扫描");populateDataToRecyclerView();}}私有无效 showProgressBar() {binding.recylerViewFilm.setVisibility(View.GONE);binding.progressBar.setVisibility(View.VISIBLE);}私有无效 hideProgressBar() {binding.recylerViewFilm.setVisibility(View.VISIBLE);binding.progressBar.setVisibility(View.GONE);}私有无效 populateDataToRecyclerView() {隐藏进度条();scanAndPairAdapter.setBleDeviceEntityList(bleDeviceEntityList);scanAndPairAdapter.notifyDataSetChanged();binding.recylerViewFilm.setLayoutManager(new LinearLayoutManager(ScanAndPairActivity.this));binding.recylerViewFilm.setHasFixedSize(true);binding.recylerViewFilm.setAdapter(scanAndPairAdapter);scanAndPairAdapter.setOnItemClickCallback(new ScanAndPairAdapter.OnItemClickCallback() {@覆盖公共无效 onItemClicked(BLEDeviceEntity bleDeviceEntity) {Toast.makeText(ScanAndPairActivity.this,尝试连接到"+ bleDeviceEntity.getName(), Toast.LENGTH_SHORT).show();}});}//BLE 扫描回调私人 ScanCallback bleScanCallback = 新 ScanCallback() {@覆盖public void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);String deviceAddress = result.getDevice().getAddress();String deviceName = result.getDevice().getName();Log.d(TAG, "ScanCallback, deviceAddress: " + deviceAddress + ", deviceName: " + deviceName);if(bleDeviceEntityList.size() == 0) {bleDeviceEntityList.add(new BLEDeviceEntity(deviceAddress, deviceName));}别的 {for(BLEDeviceEntity bleDeviceEntity : bleDeviceEntityList){if(!bleDeviceEntity.getAddress().equals(deviceAddress)) {bleDeviceEntityList.add(new BLEDeviceEntity(deviceAddress, deviceName));}}}Log.d(TAG, "bleDeviceEntityList: " + bleDeviceEntityList);}};//最新 Android BLE 应用示例的来源:https://github.com/android/connectivity-samples/tree/main/BluetoothAdvertisementsKotlin私有静态列表 构建扫描过滤器(){列表 scanFilters = new ArrayList<>();ScanFilter.Builder builder = new ScanFilter.Builder();//注释掉以下行以查看您周围的所有 BLE 设备//builder.setServiceUuid(Constants.Service_UUID);scanFilters.add(builder.build());返回扫描过滤器;}私有静态 ScanSettings buildScanSettings() {ScanSettings.Builder builder = new ScanSettings.Builder();builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);返回 builder.build();}} 感谢大家的帮助,特别感谢 Isaidamier 向我展示示例应用 这里.
I'm creating an Android app that scans all nearby BLE (Bluetooth Low Energy) devices using Android Studio.
I think I have implemented all these documentations:
- https://developer.android.com/guide/topics/connectivity/bluetooth/ble-overview
- https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java
- https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java
- https://developer.android.com/guide/topics/connectivity/bluetooth/find-ble-devices
But as you can see in the log below, (the problem) there are no BLE devices scanned by the app.
Here are the logs in the logcat:
I think it could happen because the
BLE scan callback
is not called (no BLE scan callback in the log).So my question is what is the solution for my code? Did I miss coding something?
Here is my code
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example"> <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" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Example"> <activity android:name=".ui.authentication.signin.SignInActivity" /> <activity android:name=".ui.authentication.signup.SignUpActivity" /> <activity android:name=".ui.home.HomeActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
BluetoothHelper.java:
package com.example.util; import android.Manifest; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanResult; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Handler; import android.util.Log; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; public class BluetoothHelper { static int REQUEST_ENABLE_BT = 1; static int PERMISSION_CODE = 1; static String TAG = "Bluetooth"; static boolean isScanning = false; // SOURCE FOR BLUETOOTH PERMISSION: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java // CHECK FOR BLUETOOTH PERMISSION FOR ANDROID 10 public static void android10BluetoothPermission (Context context, Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, PERMISSION_CODE ); } } } // SOURCE FOR SET UP BLUETOOTH: https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java // GET BLUETOOTH ADAPTER public static void setupBluetooth (BluetoothAdapter bluetoothAdapter) { if (bluetoothAdapter == null) { Log.d(TAG, "Bluetooth: " + "bluetooth adapter is null"); } else { Log.d(TAG, "Bluetooth: " + "bluetooth is adapter not null"); } } // ENABLE BLUETOOTH public static void enableBluetooth (Activity activity, BluetoothAdapter bluetoothAdapter) { Log.d(TAG, "Bluetooth: " + "bluetooth adapter is enabled: " + bluetoothAdapter.isEnabled()); if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); Log.d(TAG, "Bluetooth: " + "bluetooth is enabled"); } else { Log.d(TAG, "Bluetooth: " + "bluetooth is already enabled"); } } // SOURCE FOR FIND BLUETOOTH DEVICES: https://developer.android.com/guide/topics/connectivity/bluetooth/find-bluetooth-devices // QUERY PAIRED DEVICES public static Set<BluetoothDevice> queryPairedDevices (BluetoothAdapter bluetoothAdapter) { Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); Log.d(TAG, "PairedDevices: " + pairedDevices.toString()); return pairedDevices; } // GET ALL NAMES AND MAC ADDRESSES public static ArrayList<HashMap<String, String>> getNamesAndMacAddresses(Set<BluetoothDevice> bluetoothDevices) { ArrayList<HashMap<String, String>> arrayList = new ArrayList<>(); if (bluetoothDevices.size() > 0) { for (BluetoothDevice device : bluetoothDevices) { String deviceName = device.getName(); String deviceMacAddress = device.getAddress(); HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("deviceName", deviceName); hashMap.put("deviceMacAddress", deviceMacAddress); arrayList.add(hashMap); } } Log.d(TAG, "NamesAndMacAddress: " + arrayList); return arrayList; } // SOURCE FOR FIND BLE DEVICES: https://developer.android.com/guide/topics/connectivity/bluetooth/find-ble-devices#java // SCAN BLE DEVICES public static void scanBLEDevices (BluetoothLeScanner bluetoothLeScanner) { int SCAN_DURATION = 10000; if(!isScanning) { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { isScanning = false; bluetoothLeScanner.stopScan(bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "stop scanning"); } }, SCAN_DURATION); isScanning = true; bluetoothLeScanner.startScan(bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "start scanning"); } else { isScanning = false; bluetoothLeScanner.stopScan(bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "stop scanning"); } } // BLE SCAN CALLBACK private static ScanCallback bleScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); Log.d(TAG, "ScanCallback: " + result.getDevice()); } }; }
HomeActivity.java:
package com.example.ui.home; import androidx.appcompat.app.AppCompatActivity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.BluetoothLeScanner; import android.os.Bundle; import android.view.View; import com.example.R; import com.example.databinding.ActivityHomeBinding; import com.example.util.AuthenticationHelper; import com.example.util.BluetoothHelper; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; public class HomeActivity extends AppCompatActivity implements View.OnClickListener { ActivityHomeBinding binding; Set<BluetoothDevice> pairedDevices; ArrayList<HashMap<String, String>> arrayList; BluetoothLeScanner bluetoothLeScanner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityHomeBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setUpBluetooth(); binding.buttonKeluar.setOnClickListener(this); } @Override protected void onStart() { super.onStart(); AuthenticationHelper.checkHasTheUserLoggedIn(this); } @Override public void onClick(View v) { if(v.getId() == R.id.buttonKeluar) { AuthenticationHelper.signOutUser(this); } } private void setUpBluetooth() { BluetoothHelper.android10BluetoothPermission(this, HomeActivity.this); BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothHelper.setupBluetooth(bluetoothAdapter); BluetoothHelper.enableBluetooth(this, bluetoothAdapter); pairedDevices = BluetoothHelper.queryPairedDevices(bluetoothAdapter); arrayList = BluetoothHelper.getNamesAndMacAddresses(pairedDevices); bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner(); BluetoothHelper.scanBLEDevices(bluetoothLeScanner); } }
UPDATE
I added this code into
android10BluetoothPermission()
function inBluetoothHelper.java
class but still didn't work.if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_CODE ); } if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_CODE ); }
解决方案Finally, I have modified my code so the code now is working. Here it is:
ScanAndPairActivity.java (I'm creating a new activity for scanning and pairing BLE devices):
package com.example.ui.scanandpair; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.Toast; import com.example.R; import com.example.databinding.ActivityScanAndPairBinding; import com.example.entity.BLEDeviceEntity; import java.util.ArrayList; import java.util.List; public class ScanAndPairActivity extends AppCompatActivity { // GENERAL String TAG = getClass().getSimpleName(); ActivityScanAndPairBinding binding; // BLUETOOTH int REQUEST_ENABLE_BT = 1; boolean isScanning = false; BluetoothAdapter bluetoothAdapter; BluetoothLeScanner bluetoothLeScanner; ScanAndPairAdapter scanAndPairAdapter; List<BLEDeviceEntity> bleDeviceEntityList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityScanAndPairBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); android10BluetoothPermission(); scanAndPairAdapter = new ScanAndPairAdapter(this); bleDeviceEntityList = new ArrayList<>(); } // SOURCE FOR BLUETOOTH PERMISSION: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java // CHECK FOR BLUETOOTH PERMISSION FOR ANDROID 10 private void android10BluetoothPermission () { boolean isLocationPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; boolean isBGLocationAccessNotGranted = false; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { isBGLocationAccessNotGranted = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED; } boolean isLocationAccessNotGranted = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED; if (isLocationPermissionRequired && isBGLocationAccessNotGranted && isLocationAccessNotGranted) { requestLocationPermission(); } else { setUpBluetooth(); } } private void requestLocationPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder .setTitle(getString(R.string.izinkan_lokasi)) .setMessage(getString(R.string.mohon_izinkan_aplikasi_mengakses_lokasi)) .setPositiveButton(getString(R.string.ya), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { makeLocationRequest(); } }); alertDialogBuilder.show(); } else { makeLocationRequest(); } } } private void makeLocationRequest() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions(new String[]{"android.permission.ACCESS_FINE_LOCATION"}, 101); } } // ON REQUEST PERMISSION RESULT @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch(requestCode) { case 101: if (grantResults.length != 0 && grantResults[0] == 0) { setUpBluetooth(); } break; default: Toast.makeText(this, getString(R.string.maaf_izin_lokasi_harus_disetujui), Toast.LENGTH_LONG).show(); } } private void setUpBluetooth() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); checkBluetooth(bluetoothAdapter); enableBluetooth(this, bluetoothAdapter); bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner(); scanBLEDevices(bluetoothLeScanner); } // SOURCE FOR SET UP BLUETOOTH: https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java // GET BLUETOOTH ADAPTER private void checkBluetooth (BluetoothAdapter bluetoothAdapter) { if (bluetoothAdapter == null) { Log.d(TAG, "Bluetooth: " + "bluetooth adapter is null"); } else { Log.d(TAG, "Bluetooth: " + "bluetooth is adapter not null"); } } // ENABLE BLUETOOTH private void enableBluetooth (Activity activity, BluetoothAdapter bluetoothAdapter) { Log.d(TAG, "Bluetooth: " + "bluetooth adapter is enabled: " + bluetoothAdapter.isEnabled()); if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); Log.d(TAG, "Bluetooth: " + "bluetooth is enabled"); } else { Log.d(TAG, "Bluetooth: " + "bluetooth is already enabled"); } } // SOURCE FOR FIND BLE DEVICES: https://developer.android.com/guide/topics/connectivity/bluetooth/find-ble-devices#java // SCAN BLE DEVICES private void scanBLEDevices (BluetoothLeScanner bluetoothLeScanner) { showProgressBar(); int SCAN_DURATION = 5000; if(!isScanning) { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { isScanning = false; bluetoothLeScanner.stopScan(bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "stop scanning"); populateDataToRecyclerView(); } }, SCAN_DURATION); isScanning = true; showProgressBar(); bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "start scanning"); } else { isScanning = false; bluetoothLeScanner.stopScan(bleScanCallback); Log.d(TAG, "ScanBLEDevices: " + "stop scanning"); populateDataToRecyclerView(); } } private void showProgressBar() { binding.recylerViewFilm.setVisibility(View.GONE); binding.progressBar.setVisibility(View.VISIBLE); } private void hideProgressBar() { binding.recylerViewFilm.setVisibility(View.VISIBLE); binding.progressBar.setVisibility(View.GONE); } private void populateDataToRecyclerView() { hideProgressBar(); scanAndPairAdapter.setBleDeviceEntityList(bleDeviceEntityList); scanAndPairAdapter.notifyDataSetChanged(); binding.recylerViewFilm.setLayoutManager(new LinearLayoutManager(ScanAndPairActivity.this)); binding.recylerViewFilm.setHasFixedSize(true); binding.recylerViewFilm.setAdapter(scanAndPairAdapter); scanAndPairAdapter.setOnItemClickCallback(new ScanAndPairAdapter.OnItemClickCallback() { @Override public void onItemClicked(BLEDeviceEntity bleDeviceEntity) { Toast.makeText( ScanAndPairActivity.this, "try to connect to " + bleDeviceEntity.getName(), Toast.LENGTH_SHORT).show(); } }); } // BLE SCAN CALLBACK private ScanCallback bleScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); String deviceAddress = result.getDevice().getAddress(); String deviceName = result.getDevice().getName(); Log.d(TAG, "ScanCallback, deviceAddress: " + deviceAddress + ", deviceName: " + deviceName); if(bleDeviceEntityList.size() == 0) { bleDeviceEntityList.add(new BLEDeviceEntity(deviceAddress, deviceName)); } else { for(BLEDeviceEntity bleDeviceEntity : bleDeviceEntityList){ if(!bleDeviceEntity.getAddress().equals(deviceAddress)) { bleDeviceEntityList.add(new BLEDeviceEntity(deviceAddress, deviceName)); } } } Log.d(TAG, "bleDeviceEntityList: " + bleDeviceEntityList); } }; // SOURCE FOR LATEST ANDROID BLE APPLICATION SAMPLE: https://github.com/android/connectivity-samples/tree/main/BluetoothAdvertisementsKotlin private static List<ScanFilter> buildScanFilters() { List<ScanFilter> scanFilters = new ArrayList<>(); ScanFilter.Builder builder = new ScanFilter.Builder(); // Comment out the below line to see all BLE devices around you // builder.setServiceUuid(Constants.Service_UUID); scanFilters.add(builder.build()); return scanFilters; } private static ScanSettings buildScanSettings() { ScanSettings.Builder builder = new ScanSettings.Builder(); builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER); return builder.build(); } }
Thank you everyone for your help and special thanks to Isaidamier for showing me the example app here.
这篇关于扫描 BLE 设备后不调用 Android BLE 扫描回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!