当前位置: 首页 > 知识库问答 >
问题:

扫描 BLE 设备后不调用Android BLE 扫描回调

章学义
2023-03-14

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

我想我已经实施了所有这些文件:

  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

但是,正如您在下面的日志中看到的,(问题)应用程序没有扫描任何BLE设备。

以下是日志中的日志:

我认为这可能发生,因为没有调用BLE扫描回调(日志中没有BLE扫描回调)。

所以我的问题是我的代码的解决方案是什么?我错过了编码什么吗?

这是我的密码

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);
    }
}

我将这段代码添加到< code > bluetooth helper . Java 类中的< code > Android 10 bluetooth permission()函数中,但仍然无法运行。

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
            );
        }

共有1个答案

刘建中
2023-03-14

最后,我修改了我的代码,所以代码现在可以工作了。这是:

ScanAndPairActivity.java(我正在创建一个用于扫描和配对BLE设备的新活动):

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();
    }
}

感谢大家的帮助,特别感谢Isaidamier在这里向我展示了示例应用程序。

 类似资料:
  • 我试图扫描BLE设备与 (我知道它在新版本中已经过时了,但我只是想看看它是否能与我的手机配合使用[4.4],我正在使用它)。因此,它开始扫描,然后继续,没有给出错误,但没有检测到设备。也会触发OnLEScan事件,但其中的设备参数为null。我的LE设备就在那里并已连接。 在Google上,我发现如果BluetoothAdapter没有UUID,就会发生这种情况。如何设置UUID?何时调用/启动O

  • 我有3台Android设备,三星Galaxy S3手机,三星Tab4和Verizon OEM平板电脑。Verizon OEM平板电脑不支持BLE、API 17。我从android开发者网站安装了“BLE设备扫描”,并在Galaxy S3上运行。它只显示Verizon平板电脑是找到的设备。当我在三星Tab4上运行相同的应用程序时,它只显示Galaxy S3作为找到的设备。如果我只看Galaxy S3

  • 我想在我的Android应用程序中被动地扫描BLE广告商, 但我找不到如何做到这一点。 > < li> 根据蓝牙4.0核心规范,存在被动扫描模式。< br >第6卷:核心系统包[低能耗控制器卷],< br > D部分:4.1被动扫描< br > https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282159 “设备可

  • 我试图用BLE API扫描附近的蓝牙设备,但它似乎不起作用 我已经在清单中添加了权限 以下内容在创建对象时 创建扫描仪回调对象并进一步扫描 在logcat中,我只看到以下内容 这是我的app build gradle } 有人能指出我在这里遗漏了什么吗?

  • 开启蓝牙扫描 参数说明 字段 类型 必须? 说明 blePrefix String 是 设备名称类型前缀 示例代码 Swift: RokidMobileSDK.binder.startBLEScan(blePrefix: String) ->Bool Objc: [RokidMobileSDK.binder startBLEScanWithBlePrefix:@"Rokid-"]; 手机蓝牙未打

  • 扫描设备 介绍 需要传入扫描蓝牙设备的名称的前缀,回调均在主线程。如果传空,是无法获取设备列表。 1、单前缀蓝牙设备 参数说明 字段 类型 必须? 说明 type String 是 设备名称类型前缀 举个大栗子 String type = "Rokid-" RokidMobileSDK.binder.startBTScan(type, new IBTScanCallBack() { @Ov