kotlin 如何在Android上使用BLE 2M PHY通过蓝牙LeAdvertiser发布广告AdvertiseData

myzjeezk  于 2023-01-05  发布在  Kotlin
关注(0)|答案(1)|浏览(295)

我目前正在构建一个基于蓝牙低功耗广告的聊天应用程序。我尝试构建一个遵循tutorial by android的客户端,但我的BluetoothLeScanner似乎无法检索任何BLE 2M PHY scanResults。我能够使用nRF Connect应用程序实现所需的结果,因此这可能不是硬件问题

class BluetoothAdvertiser(private var bluetoothAdapter: BluetoothAdapter) {
    private val TAG: String = BluetoothAdvertiser::class.java.simpleName
    private var advertiseUUID: ParcelUuid =
        ParcelUuid(UUID.fromString("e889813c-5d19-49e2-8bc4-d4596b4f5250"))
    private var advertiser: BluetoothLeAdvertiser = bluetoothAdapter.bluetoothLeAdvertiser
    private var maxDataLength: Int = 0
    private lateinit var currentAdvertisingData: AdvertiseData
    private lateinit var currentAdvertisingSet: AdvertisingSet

    fun init(): Boolean {
        Log.d(TAG, "init: ")
        if (!this.checkDeviceHardware()) {
            return false
        }
        this.initAdvertiser("123")
        return true
    }

    private fun checkDeviceHardware(): Boolean {
        if (!this.bluetoothAdapter.isLe2MPhySupported) {
            Log.e(TAG, "init: 2M PHY not supported")
            return false
        }
        if (!this.bluetoothAdapter.isLeExtendedAdvertisingSupported) {
            Log.e(TAG, "init: LE Extended Advertising not supported")
            return false
        }
        this.maxDataLength = this.bluetoothAdapter.leMaximumAdvertisingDataLength
        Log.d(TAG, "init: leMaximumAdvertisingDataLength: " + this.maxDataLength)
        return true
    }

    private fun initAdvertiser(message: String): Boolean {
        val setParameters: AdvertisingSetParameters = AdvertisingSetParameters.Builder()
            .setLegacyMode(false)
            .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
            .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MEDIUM)
            .setPrimaryPhy(BluetoothDevice.PHY_LE_CODED)
            .setSecondaryPhy(BluetoothDevice.PHY_LE_2M)
            .build()
        val advertiseData: AdvertiseData = AdvertiseData.Builder()
            .setIncludeDeviceName(true)
            .addServiceUuid(advertiseUUID)
            .addServiceData(advertiseUUID, message.encodeToByteArray())
            .build()
        val periodicParameters: PeriodicAdvertisingParameters = PeriodicAdvertisingParameters.Builder()
            .setInterval(800)
            .build()
        return try {
            this.advertiser.startAdvertisingSet(
                setParameters,
                advertiseData,
                advertiseData,
                periodicParameters,
                advertiseData,
                this.advertisingSetCallback
            )
            true
        } catch (e: SecurityException) {
            Log.w(TAG, "initAdvertiser: ",e)
            false
        }
    }

     fun changeAdvertisingData(message: String){
        try{
            Log.d(TAG, "changeAdvertisingData: message: $message" )
            this.currentAdvertisingSet.setAdvertisingData(AdvertiseData.Builder().addServiceData(this.advertiseUUID,message.encodeToByteArray()).build())
        } catch (e: SecurityException) {
            Log.w(TAG, "initAdvertiser: ",e)
        }
    }

    private var advertisingSetCallback: AdvertisingSetCallback = object : AdvertisingSetCallback() {
        override fun onAdvertisingSetStarted(
            advertisingSet: AdvertisingSet,
            txPower: Int,
            status: Int
        ) {
            Log.i(
                TAG, "onAdvertisingSetStarted(): txPower:  $txPower  , status: $status "
            )
            currentAdvertisingSet = advertisingSet
        }

        override fun onAdvertisingSetStopped(advertisingSet: AdvertisingSet) {
            Log.i(TAG, "onAdvertisingSetStopped():")
        }
    }
6tr1vspr

6tr1vspr1#

上面的代码工作正常,但是我没有为非传统广告设置BluetoothLeScanner,下面是我现在工作的扫描器

class BluetoothScanner(private var bluetoothLeScanner: BluetoothLeScanner) : ScanCallback() {
    private val TAG: String = BluetoothScanner::class.java.simpleName
    private var scanning = false
    private var advertiseUUID: ParcelUuid =
        ParcelUuid(UUID.fromString("e889813c-5d19-49e2-8bc4-d4596b4f5250"))
    private var scanSettings: ScanSettings
    private var scanFilter: ScanFilter

    init {
        this.scanSettings = ScanSettings.Builder()
            .setLegacy(false)
            .setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED)
            .build()
        this.scanFilter = ScanFilter.Builder()
            .setServiceUuid(advertiseUUID)
            .build()
    }

    fun startScan(): Boolean {
        Log.d(TAG, "startScan: ")
        if (scanning) {
            this.stopScan()
        }
        if (!this.scanning) {
            return try {
                this.bluetoothLeScanner.startScan(listOf(this.scanFilter),this.scanSettings, this)
                this.scanning = true
                true
            } catch (e: SecurityException) {
                Log.w(TAG, "startScan: ", e)
                false
            }
        }
        return false
    }

相关问题