首页 > 解决方案 > 使用 startDiscovery 扫描蓝牙设备但未找到设备

问题描述

我在 Kotlin 中编写并能够设置一个接收器来处理由 startDiscovery 引起的 ACTION_DISCOVERY_STARTED 和 ACTION_DISCOVERY_FINISHED 事件(我将消息打印到文本视图并查看它们是否有效)。

但是,ACTION_FOUND 永远不会在接收器中被调用(当应该找到设备时,我从未看到我在该例程中更新的文本视图更改)。

我拥有清单中的所有权限(以及更多权限):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test_ble">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<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.Test_BLE">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

我有两个文本视图。text_view1 用于报告扫描状态,text_view2 用于放置扫描设备列表。这些设备(目前很粗略)只是连接到一个字符串,然后分配给 text_view2.text。但是,我从未看到该列表得到更新。

我知道房间里还有其他蓝牙设备在做广告,因为我可以在华硕 Nexus 7 平板电脑(Android 6.1)上看到它们,我用它来测试蓝牙设备设置下的代码。

minSdk 在 21 时应该足够低。这是 buildgradle 模块脚本:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}
android {
    compileSdk 31
    defaultConfig {
        applicationId "com.example.test_ble"
        minSdk 21
        targetSdk 31
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures{
        viewBinding = true
    }
}
dependencies {
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

这是 MainActivity.kt 文件。

package com.example.test_ble

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.test_ble.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var btAdapter: BluetoothAdapter
    private var deviceList: String = ""
    // *****************************************************
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        // Get the BluetoothAdapter
        btAdapter = BluetoothAdapter.getDefaultAdapter()
        if (btAdapter == null) {
            binding.textView1.text = "No Bt Adapter!"
        } else if (!btAdapter.isEnabled) {
            binding.textView1.text = "Bt Adapter is NOT ENABLED!"
        } else {
            binding.textView1.text = "Bt Adapter is ENABLED!"

            // Build receiver for Device Discovery
            val receiver = object : BroadcastReceiver() {
                override fun onReceive(context: Context, intent: Intent) {
                    when (intent.action) {
                        BluetoothAdapter.ACTION_DISCOVERY_STARTED -> {
                            // Device discovery started, show loading indication
                            binding.textView1.text = "Device discovery started"
                        }
                        BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
                            // unregister receiver and hide loading indication
                            binding.textView1.text = "Device discovery finished"
                        }
                        BluetoothDevice.ACTION_FOUND -> {
                            binding.textView1.text = "ACTION_FOUND" // I never see this message
                            val device: BluetoothDevice? =
                                intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                            val deviceName = device?.name
                            val deviceHardwareAddress = device?.address // MAC address
                            deviceList =
                                deviceList + "\n" + deviceName.toString() + " " + deviceHardwareAddress.toString()
                            binding.textView2.text = deviceList // The device list is never updated
                        }
                    }
                }
            }
            // Register for broadcasts when a device is discovered.
            val intentFilter = IntentFilter().apply {
                addAction(BluetoothDevice.ACTION_FOUND)
                addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
                addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
            }
            if (btAdapter.isDiscovering()) {
                btAdapter.cancelDiscovery();
            }
            registerReceiver(receiver, intentFilter)
            btAdapter.startDiscovery()
        }
    }
}

谁能看到我错过了什么或做错了什么?当我确实看到发现的开始和结束确实发生时,我不明白为什么我没有检测到任何设备。在搜索并尝试了我在网上可以找到的所有内容后,我没有想法。非常感谢帮助。

吉姆

标签: androidkotlinbluetoothandroid-bluetooth

解决方案


您已在中声明了权限,Manifest但您是否要求用户允许ACCESS_FINE_LOCATION&ACCESS_COARSE_LOCATION权限?或者您可以通过转到设置中的应用信息然后尝试发现设备来允许这些权限。如果您的应用能够发现,那么您可能需要询问runtime permissions用户。


推荐阅读