扫描 BLE 设备后不调用 Android BLE 扫描回调 [英] Android BLE Scan Callback is not called after scanning for BLE devices

查看:83
本文介绍了扫描 BLE 设备后不调用 Android BLE 扫描回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个使用 Android Studio 扫描附近所有 BLE(低功耗蓝牙)设备的 Android 应用.

我想我已经实现了所有这些文档:

  1. 我认为这可能是因为未调用 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 alertDialogBu​​ilder = 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();}});alertDialogBu​​ilder.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:

    1. https://developer.android.com/guide/topics/connectivity/bluetooth/ble-overview
    2. https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#java
    3. https://developer.android.com/guide/topics/connectivity/bluetooth/setup#java
    4. 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 in BluetoothHelper.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆