首页 > 解决方案 > 在 Android Studio 上的 Fragment 中扫描 BLE 设备 - Kotlin

问题描述

几天来,我试图在我的应用程序中实现 BLE 连接。我在次要片段而不是主要片段中这样做。但是当我扫描找到一个 BLE 设备(使用 startScan( leScanCallback))时,它永远不会进入回调方法leScanCallback。我遵循了一些教程,但我不知道为什么它不起作用。

这是我的 MainActivity.kt

package com.example.start


class MainActivity : AppCompatActivity() {

    private lateinit var drawerLayout: DrawerLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        drawerLayout = binding.drawerLayout
        val navController = this.findNavController(R.id.myNavHostFragment)
        NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)   //link the navigation controller & drawer layout to the app bar
        NavigationUI.setupWithNavController(binding.navView, navController) //allows the user to display the navigation drawer

        //PERMISSION
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            if (ContextCompat.checkSelfPermission(baseContext,
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
                val PERMISSION_CODE = 0 //Should be >= 0
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                    PERMISSION_CODE)
            }
        }

        //==========================Bluetooth Part==========================================
        val REQUEST_ENABLE_BT : Int = 1 //Will stock the result of enabling the bluetooth
                                        //RESULT_OK =  -1 (0xffffffff)
                                        //RESULT_CANCELLED = 0 (0x00000000)
        //val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
        val bluetoothAdapter: BluetoothAdapter by lazy {
            val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
            bluetoothManager.adapter
        }
        if (bluetoothAdapter == null) {
            // Device doesn't support Bluetooth
        }
        if (bluetoothAdapter?.isEnabled == false) { //If bluetooth is disable, we active it
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
        }
    }
}

这是我的 ConnectFragment.kt,我按下按钮“btnScan”开始研究

package com.example.start

private const val SELECT_DEVICE_REQUEST_CODE = 0

class ConnectFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        //return inflater.inflate(R.layout.fragment_connect, container, false)
        val binding = DataBindingUtil.inflate<FragmentConnectBinding>(
                inflater, R.layout.fragment_connect, container, false
        )
        binding.btnScan.setOnClickListener {
            view : View ->
            scanLeDevice()
        }
        return binding.root
    }

    private val bluetoothLeScanner: BluetoothLeScanner
        get() {
            val bluetoothManager = requireContext().getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
            val bluetoothAdapter = bluetoothManager.adapter
            return bluetoothAdapter.bluetoothLeScanner
        }
    // Device scan callback.
    private val leScanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            super.onScanResult(callbackType, result)
            //TODO TEST TEST TEST
            Log.d("ScanDeviceActivity", "leScanCallback >>")
            Log.d("ScanDeviceActivity", "onScanResult(): ${result?.device?.address} - ${result?.device?.name}")
        }
        override fun onBatchScanResults(results: MutableList<ScanResult>?) {
            super.onBatchScanResults(results)
            Log.d("DeviceListActivity","onBatchScanResults:${results.toString()}")
        }

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
            Log.d("DeviceListActivity", "onScanFailed: $errorCode")
        }
    }
    private var scanning = false
    private val handler = Handler()
    // Stops scanning after 10 seconds.
    private val SCAN_PERIOD: Long = 10000

    fun scanLeDevice() {
        if (!scanning) { // Stops scanning after a pre-defined scan period.
            handler.postDelayed({
                scanning = false
                bluetoothLeScanner.stopScan(leScanCallback)
            }, SCAN_PERIOD)
            scanning = true
            //PERMISSION COARSE LOCATION
            Log.d("ScanDeviceStart", "startScan()")
            when (PermissionChecker.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION)) {
                PackageManager.PERMISSION_GRANTED -> bluetoothLeScanner.startScan(leScanCallback)
                else -> requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), 1)
            }
        } else {
            scanning = false
            bluetoothLeScanner.stopScan(leScanCallback)
        }
    }

    //Permission
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        when (requestCode) {
            1 -> when (grantResults) {
                intArrayOf(PackageManager.PERMISSION_GRANTED) -> {
                    Log.d("ScanDevices", "onRequestPermissionsResult(PERMISSION_GRANTED)")
                    bluetoothLeScanner.startScan(leScanCallback)
                }
                else -> {
                    Log.d("ScanDevices", "onRequestPermissionsResult(not PERMISSION_GRANTED)")
                }
            }
            else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }
}

按下按钮后,调试控制台以: D/BluetoothLeScanner: Stop Scan with callback结尾

标签: androidkotlinandroid-fragmentsbluetoothbluetooth-lowenergy

解决方案


推荐阅读