关于android:手记|Android-获取已配对蓝牙列表和已连接蓝牙名称

28次阅读

共计 7908 个字符,预计需要花费 20 分钟才能阅读完成。

  • 手记 | MobPush 接入总结
  • Gradle 手记|盘点我应用过的 build 根本配置(不断更新中。。。
  • Git 手记 | 总结集体日常开发罕用到的一些命令(不断更新。。。
  • Utils 手记 | Android Studio 插件整顿(不断更新中 …
  • 手记|Kotlin 根底类型回顾
  • 手记|Android 获取已配对蓝牙列表和已连贯蓝牙名称

最近正好我的项目有蓝牙需要,折腾了小一会儿,特意记录一下~

网上好多搜寻到的文章没法用,难堪死。。。或者就是 Java 版本,转 Kotlin 多少有点坑,不过更加加深了要好好学习一下 Kotlin 的想法~

附上脑图:

Demo GitHub 地址:

  • https://github.com/HLQ-Strugg…

蓝牙简述

蓝牙的呈现,让挪动设施多了一种替换数据的形式,而 Android 利用能够通过 Bluetooth Api 执行如下操作:

  • 扫描其余蓝牙设施
  • 查问本地蓝牙适配器的配对蓝牙设施
  • 建设 RFCOMM 通道
  • 通过服务发现连贯到其余设施
  • 与其余设施进行双向数据传输
  • 治理多个连贯

而咱们明天,次要是进行第二点,查问本地蓝牙适配器的配对蓝牙设施。

传统的蓝牙实用于较为耗电的操作,其中包含 Android 设施之间的流式传输和通信等。而针对具备低功耗要求的蓝牙设施,Android 4.3(API 18)中引入面向低功耗蓝牙的 API 反对。

1、基础知识

为了让蓝牙设施能够在彼此之间传输数据,必须先通过配对过程造成通道。

其中一台设施须要将本身设置为可接管传入的连贯申请,另一台设施则通过服务发现过程并找到可检测的设施。

随后在检测到的设施承受配对申请后,设施之间实现绑定操作,并在此期间替换平安密钥。 二者会缓存这些密钥,以供日后应用。

实现配对和绑定过程后,两台设施会替换信息。

当会话实现时,发动配对申请的设施会将其链接到可检测设施的通道。

并且这俩台设施依然放弃绑定状态, 因而在将来的会话期间,只有两者在彼此的范畴内且均为移除绑定,便会主动连贯。

2、蓝牙权限

根底权限必须申明:

<uses-permission android:name="android.permission.BLUETOOTH" />

如果想对蓝牙进行相干操作,比方关上蓝牙等,须要配置如下权限:

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

而当利用须要扫描其余设施时,须要申明如下权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

这里须要留神的:

  • 如果利用适配 Android 9(Api 28)或者更低版本,则能够申明 ACCESS_COARSE_LOCATION 权限,而非 ACCESS_FINE_LOCATION 权限。

如果须要申明以后利用仍然实用于不反对 BLE 的设施,则须要在权限中增加如下元素:

<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>

蓝牙 Demo 搞起(获取已配对列表以及已连贯蓝牙名称)

1、必不可少的权限

<uses-permission android:name="android.permission.BLUETOOTH" />

2、工具类

package com.hlq.bluetoothpro.utils

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothProfile
import android.content.Context
import android.media.AudioManager
import android.util.Log
import java.lang.reflect.InvocationTargetException

/**
 * @author:HLQ_Struggle
 * @date:2021/8/29
 * @desc:*/

private var mBluetoothAdapter: BluetoothAdapter? = null

/**
 * 实例化 BluetoothAdapter
 */
private fun getInstance(): BluetoothAdapter? {if (mBluetoothAdapter == null) {mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
    }
    return mBluetoothAdapter
}

/**
 * 检测设施是否反对蓝牙
 */
fun checkBluetoothEnable(): Boolean {return getInstance() == null
}

/**
 * 判断以后蓝牙是否关上
 */
fun checkBluetoothStateEnable(): Boolean {return getInstance()?.isEnabled == true
}

/**
 * 获取蓝牙耳机连贯状态
 */
private fun isWiredHeadsetConnected(context: Context): Boolean {
    try {val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        return audioManager.isWiredHeadsetOn
    } catch (e: Exception) { }
    return false
}

/**
 * 判断蓝牙耳机是否已连贯
 */
fun hasBluetoothAudioDevice(): Boolean {val adapter = BluetoothAdapter.getDefaultAdapter()
    var a2dp = false
    var headset = false
    try {
        a2dp =
            adapter.getProfileConnectionState(BluetoothProfile.A2DP) != BluetoothProfile.STATE_DISCONNECTED
        headset =
            adapter.getProfileConnectionState(BluetoothProfile.HEADSET) != BluetoothProfile.STATE_DISCONNECTED
    } catch (e: Throwable) { }
    return a2dp || headset
}

/**
 * 获取到已配对胜利蓝牙设施
 */
fun fetchAlReadyConnection() {getInstance()?.let {
        val devices = it.bondedDevices
        for (device in devices) {
            Log.e(
                "HLQ", "---->" +
                        "name ${device.name}" +
                        "address ${device.address}" +
                        "bondState ${device.bondState}" +
                        "type ${device.type} ${device.uuids.size}"
            )
        }
    }
}

fun getConnectedBtDevice(): String? {
    // 获取蓝牙适配器
    val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
    // 失去已匹配的蓝牙设施列表
    val bondedDevices = bluetoothAdapter.bondedDevices
    if (bondedDevices != null && bondedDevices.size > 0) {for (bondedDevice in bondedDevices) {
            try {
                // 应用反射调用被暗藏的办法
                val isConnectedMethod =
                    BluetoothDevice::class.java.getDeclaredMethod("isConnected")
                isConnectedMethod.isAccessible = true
                val isConnected =
                    isConnectedMethod.invoke(bondedDevice) as Boolean
                if (isConnected) {return bondedDevice.name}
            } catch (e: NoSuchMethodException) {e.printStackTrace()
            } catch (e: IllegalAccessException) {e.printStackTrace()
            } catch (e: InvocationTargetException) {e.printStackTrace()
            }
        }
    }
    return null
}

3、创立监听蓝牙播送

package com.hlq.bluetoothpro.receiver

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 android.util.Log
import com.hlq.bluetoothpro.utils.checkBluetoothStateEnable
import com.hlq.bluetoothpro.utils.fetchAlReadyConnection
import com.hlq.bluetoothpro.utils.getConnectedBtDevice
import com.hlq.bluetoothpro.utils.hasBluetoothAudioDevice

/**
 * @author:HLQ_Struggle
 * @date:2021/8/28
 * @desc:*/
class BluetoothReceiver : BroadcastReceiver() {

    companion object {fun registerIntentFilter(): IntentFilter {val intentFilter = IntentFilter()
            intentFilter.apply {addAction(BluetoothAdapter.ACTION_STATE_CHANGED); // 蓝牙状态扭转
                addAction("android.bluetooth.BluetoothAdapter.STATE_OFF"); // 本地蓝牙适配器已敞开
                addAction("android.bluetooth.BluetoothAdapter.STATE_ON"); // 本地蓝牙适配器已关上,能够应用
                addAction(BluetoothDevice.ACTION_ACL_CONNECTED); // 已和近程设施建设 ACL 连贯
                addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); // 与近程设施 ACL 断开连接
                priority = Int.MAX_VALUE
            }
            return intentFilter
        }

    }

    override fun onReceive(context: Context?, intent: Intent?) {
        val action = intent?.action
        action ?: return
        val bluetoothLog = when (action) {
            BluetoothAdapter.ACTION_STATE_CHANGED -> { // 监听蓝牙状态
                when (val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {
                    BluetoothAdapter.STATE_TURNING_ON -> {"STATE_TURNING_ON 蓝牙开启中"}
                    BluetoothAdapter.STATE_ON -> {"STATE_ON 蓝牙开启"}
                    BluetoothAdapter.STATE_CONNECTING -> {"STATE_CONNECTING 蓝牙连贯中"}
                    BluetoothAdapter.STATE_CONNECTED -> {"STATE_CONNECTED 蓝牙已连贯"}
                    BluetoothAdapter.STATE_DISCONNECTING -> {"STATE_DISCONNECTING 蓝牙断开中"}
                    BluetoothAdapter.STATE_DISCONNECTED -> {"STATE_DISCONNECTED 蓝牙已断开"}
                    BluetoothAdapter.STATE_TURNING_OFF -> {"STATE_TURNING_OFF 蓝牙敞开中"}
                    BluetoothAdapter.STATE_OFF -> {"STATE_OFF 蓝牙敞开"}
                    else -> "ACTION_STATE_CHANGED EXTRA_STATE $state"
                }
            }
            BluetoothDevice.ACTION_ACL_CONNECTED -> { // 蓝牙已连贯
                Log.e("HLQ", "----> ACTION_ACL_CONNECTED 蓝牙已连贯") // 蓝牙已关上 且 已连贯
                Log.e("HLQ", "----> 蓝牙已关上且已连贯")
                Log.e("HLQ", "----> 输入已配对胜利蓝牙列表")
                Log.e("HLQ", "----> ${fetchAlReadyConnection()}")

                "----> 以后连贯蓝牙名称:${getConnectedBtDevice()}"
            }
            BluetoothDevice.ACTION_ACL_DISCONNECTED -> { // 蓝牙已断开
                "ACTION_ACL_DISCONNECTED 蓝牙已断开"
            }
            else -> "action $action"
        }
        Log.e("HLQ", "----> bluetoothLog $bluetoothLog")
    }

}

4、蓝牙注册、移除以及获取

package com.hlq.bluetoothpro

import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.hlq.bluetoothpro.receiver.BluetoothReceiver
import com.hlq.bluetoothpro.utils.*

class MainActivity : AppCompatActivity() {

    /**
     * 蓝牙监听 行车模式
     */
    private var mBluetoothFilter: IntentFilter? = null
    private var mBluetoothReceiver: BluetoothReceiver? = null

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        handleBluetooth()}

    private fun handleBluetooth() {
        // 验证以后设施是否反对蓝牙 反对便进行初始化
        if (!checkBluetoothEnable()) {Log.e("HLQ", "----> 以后设施反对蓝牙")
            initBluetooth()
            if (checkBluetoothStateEnable() && hasBluetoothAudioDevice()) { // 蓝牙已关上 且 已连贯
                Log.e("HLQ", "----> 蓝牙已关上且已连贯")
                Log.e("HLQ", "----> 输入已配对胜利蓝牙列表")
                Log.e("HLQ", "----> ${fetchAlReadyConnection()}")
                Log.e("HLQ", "----> 以后连贯蓝牙名称:${getConnectedBtDevice()}")
            }
        }
    }

    /**
     * 初始化行车模式 蓝牙监听
     */
    private fun initBluetooth() {if (mBluetoothReceiver == null) {mBluetoothReceiver = BluetoothReceiver()
        }
        if (mBluetoothFilter == null) {mBluetoothFilter = BluetoothReceiver.registerIntentFilter()
        }
        if (mBluetoothReceiver != null && mBluetoothFilter != null) {registerReceiver(mBluetoothReceiver, mBluetoothFilter)
        }
    }

    override fun onDestroy() {super.onDestroy()
        // 清理蓝牙播送
        if (mBluetoothReceiver != null) {unregisterReceiver(mBluetoothReceiver)
            mBluetoothReceiver = null
        }
    }

}

来吧,日志展现

  • 当蓝牙已关上且蓝牙已连贯
E/HLQ: ----> 以后设施反对蓝牙
E/HLQ: ----> 输入已配对胜利蓝牙列表
E/HLQ: ----> 蓝牙已关上且已连贯
E/HLQ: ----> name Earbuds X1 address E0:9D:FA:CA:4C:DF bondState 12 type 1 3
E/HLQ: ----> 以后连贯蓝牙名称:Earbuds X1
  • 当蓝牙已关上且开始连贯蓝牙(之前配对胜利过,主动连贯)
 E/HLQ: ----> 以后设施反对蓝牙
 E/HLQ: ----> 蓝牙已关上且已连贯
 E/HLQ: ----> 输入已配对胜利蓝牙列表
 E/HLQ: ----> name Earbuds X1 address E0:9D:FA:CA:4C:DF bondState 12 type 1 3 
 E/HLQ: ----> 以后连贯蓝牙名称:Earbuds X1
  • 再来个蓝牙开关展现
 E/HLQ: ----> bluetoothLog STATE_TURNING_OFF 蓝牙敞开中
 E/HLQ: ----> bluetoothLog STATE_OFF 蓝牙敞开
 E/HLQ: ----> bluetoothLog STATE_TURNING_ON 蓝牙开启中
 E/HLQ: ----> bluetoothLog STATE_ON 蓝牙开启
 E/HLQ: ----> ACTION_ACL_CONNECTED 蓝牙已连贯 
 E/HLQ: ----> 蓝牙已关上且已连贯
 E/HLQ: ----> 输入已配对胜利蓝牙列表
 E/HLQ: ----> name Earbuds X1 address E0:9D:FA:CA:4C:DF bondState 12 type 1 3
 E/HLQ: ----> kotlin.Unit
 E/HLQ: ----> bluetoothLog ----> 以后连贯蓝牙名称:Earbuds X1

THK

  • 蓝牙概览
  • 蓝牙低功耗概览

正文完
 0