我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android12 蓝牙适配的实现步骤

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android12 蓝牙适配的实现步骤

前言

在我的申请下,公司终于购买了一台基于Android12.0的手机,然后我就开心的拿去安装测试了,发现程序崩溃了,于是我这里就写下来,Android12.0的蓝牙适配方法。

在这里插入图片描述

在Android系统版本中,蓝牙的变化有,但是不多,这里简要说明一下。

一、Android版本中蓝牙简介

  • Android1.5 中增加了蓝牙功能,立体声 Bluetooth 支持:A2DP [Advanced Audio Distribution Profile]、AVCRP [Audio/Video Remote Control Profile],自动配对。
  • Android2.0 中支持Bluetooth2.1协议。
  • Android3.0 中能让应用查询已经连接上 Bluetooth 设备的 Bluetooth Profile、音频状态等,然后通知用户。
  • Android3.1 中系统可以通过 Bluetooth HID 方式同时接入一到多款输入设备。
  • Android4.0 中新增支持连接 Bluetooth HDP [Health Device Profile)] 设备,通过第三方应用的支持,用户可以连接到医院、健身中心或者家庭等场合中的无线医疗设备和传感器。
  • Android4.2 中引入了一种新的针对 Android 设备优化的 Bluetooth 协议栈 BlueDroid,从而取代 BlueZ 协议栈。Bluedroid 协议栈由 Google 和 Broadcom 公司共同开发,相对于 BlueZ 协议栈,BlueDroid 提升了兼容性和可靠性。
  • Android4.3 中增加了对低功耗蓝牙的支持,内置支持 Bluetooth AVRCP 1.3,基于 Google 和 Broadcom 公司功能研发的针对于 Android 设备优化的新的蓝牙协议栈 BlueDroid。
  • Android4.4 中新增两种新 Proifle 支持:HID [Human Interface Device]、MAP [Message Access Profile]
  • Android5.0 中支持Bluetooth4.1协议。
  • Android6.0 中扫描蓝牙需要动态获取定位才行。
  • Android7.0 中支持Bluetooth4.2协议。
  • Android8.0 中支持Bluetooth5.0协议,强化了蓝牙音频的表现。比如编码/传输格式可选SBC、AAC、aptX/aptX HD、LDAC等四种,音质依次提高。
  • Android10.0 中支持Bluetooth5.1协议,在5.0的基础上,增加了侧向功能和厘米级定位服务,大幅度提高了定位精度。使室内定位更精准。
  • Android11.0 中支持Bluetooth5.2协议,增强版ATT协议,LE功耗控制和信号同步,连接更快,更稳定,抗干扰性更好。
  • Android12.0 中支持Bluetooth5.3协议,增强了经典蓝牙BR/EDR(基础速率和增强速率)的安全性。蓝牙5.3的延迟更低、抗干扰性更强、提升了电池续航时间。系统引入了新的运行时权限 BLUETOOTH_SCAN、BLUETOOTH_ADVERTISE 和 BLUETOOTH_CONNECT权限,用于更好地管理应用于附近蓝牙设备的连接。

二、新建项目

在Android12.0中新增加了三个运行时权限,我们依次来说明一下,这里我们依然创建一个项目来说明,新建一个Android12Bluetooth项目,如下图所示:

在这里插入图片描述

这里使用Kotlin来写,点击Finish。

① 配置settings.gradle和build.gradle

然后来配置一下项目的依赖库,首先是在工程的settings.gradle中增加如下依赖:

maven { url "https://jitpack.io" }

增加位置如下图所示:

在这里插入图片描述

然后在app的build.gradle中增加

	buildFeatures {
        viewBinding true
        dataBinding true
    }

	implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'

增加位置如下图所示:

在这里插入图片描述

然后Sync Now。

② 配置AndroidManifest.xml

下面配置AndroidMainfest.xml,权限如下所示:

	<uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <!--Android12 的蓝牙权限 如果您的应用与已配对的蓝牙设备通信或者获取当前手机蓝牙是否打开-->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <!--Android12 的蓝牙权限 如果您的应用查找蓝牙设备(如蓝牙低功耗 (BLE) 外围设备)-->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <!--Android12 的蓝牙权限 如果您的应用使当前设备可被其他蓝牙设备检测到-->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>

增加位置如下图所示:

在这里插入图片描述

三、打开蓝牙

下面我们构建一下activity_main.xml中的代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/btn_open_bluetooth"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="10dp"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:text="打开蓝牙"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

这里就是写一个按钮,用来点击打开系统蓝牙的开关的。在Android12.0之前打开蓝牙的之前需要先判断蓝牙是否打开,我们可以这样来写,在MainActivity中增加如下代码:

	private fun isOpenBluetooth(): Boolean {
        val manager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
        val adapter = manager.adapter ?: return false
        return adapter.isEnabled
    }

同样我们还需要一个方法判断当前是否为Android12及以上版本。

private fun isAndroid12() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S

同样还有一个检查此权限是否授予的方法和一个显示Toast的方法:

	private fun hasPermission(permission: String) =
        checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

    private fun showMsg(msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    }

① 打开蓝牙意图

在MainActivity中新增如下代码:

	//打开蓝牙意图
    val enableBluetooth = registerForActivityResult(StartActivityForResult()) {
        if (it.resultCode == Activity.RESULT_OK) {
            showMsg(if (isOpenBluetooth()) "蓝牙已打开" else "蓝牙未打开")
        }
    }

此方法就替代了之前startActivityForResult,现在我们使用registerForActivityResult。再返回中可以得知当前是否打开了蓝牙。

② 请求BLUETOOTH_CONNECT权限意图

registerForActivityResult不光能用于页面获取值,也能用于请求权限。

	//请求BLUETOOTH_CONNECT权限意图
    val requestBluetoothConnect = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) {
                //打开蓝牙
                enableBluetooth.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
            } else {
                showMsg("Android12中未获取此权限,则无法打开蓝牙。")
            }
        }

请求权限返回无非就是同意不同意,如果同意了我们就调用

enableBluetooth.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))

去打开系统蓝牙,不同意就提示一下。下面再用ViewBinding来配置一下:

在这里插入图片描述

这里有一个initView的函数,在这个函数中我们对按钮的点击事件进行操作,新增initView()函数,代码如下:

	private fun initView() {
        binding.btnOpenBluetooth.setOnClickListener {
            //蓝牙是否已打开
            if (isOpenBluetooth()){
                showMsg("蓝牙已打开")
                return@setOnClickListener
            }
            //是Android12
            if (isAndroid12()) {
                //检查是否有BLUETOOTH_CONNECT权限
                if (hasPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
                    //打开蓝牙
                    enableBluetooth.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
                } else {
                    //请求权限
                    requestBluetoothConnect.launch(Manifest.permission.BLUETOOTH_CONNECT)
                }
                return@setOnClickListener
            }
            //不是Android12 直接打开蓝牙
            enableBluetooth.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
        }
    }

这里的代码就比较好理解,首先判断蓝牙是否已经打开了,打开了就不往下执行,没打开,再判断当前是否为Android12,不是就直接打开系统蓝牙,是Android12,再去检查是否授予BLUETOOTH_CONNECT权限,授予了就打开系统蓝牙,没有授予就去请求此权限,下面我们运行一下:

在这里插入图片描述

四、蓝牙扫描

在Android6.0 - Android11.0之间,扫描蓝牙都是需要打开定位权限的,而在Android12中则不需要了,换成了BLUETOOTH_SCAN权限,那么我们下面来看看,怎么操作的。

这里扫描蓝牙就以低功耗蓝牙为例子。

① 扫描者

在MainActivity中定义如下变量

	private val TAG = MainActivity::class.java.simpleName

    //获取系统蓝牙适配器
    private lateinit var mBluetoothAdapter: BluetoothAdapter

    //扫描者
    private lateinit var scanner: BluetoothLeScanner

    //是否正在扫描
    var isScanning = false

获取系统蓝牙适配器,要在onCreate回调中,如下图所示:

在这里插入图片描述

② 扫描回调

扫描设备时会有扫描的结果,在MainActivity中增加如下代码:

	//扫描结果回调
    private val scanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            val device = result.device
            Log.d(TAG, "name: ${device.name}, address: ${device.address}")
        }
    }

这里可能你的device.name下面会有一个红线,这是因为AS会检查你这里需要一个BLUETOOTH_CONNECT权限,而这个权限我们在打开蓝牙时已经请求过了,那么为了避免麻烦,我们在当前MainActivity上面增加如下注解。

@SuppressLint("MissingPermission")

如下图所示:

在这里插入图片描述

这个注解加上去之后你需要小心蓝牙权限的问题。

③ 扫描方法

下面我们写一个开始扫描和停止扫描的方法,代码如下:

	private fun startScan() {
        if (!isScanning) {
            scanner.startScan(scanCallback)
            isScanning = true
            binding.btnScanBluetooth.text = "停止扫描"
        }
    }

    private fun stopScan() {
        if (isScanning) {
            scanner.stopScan(scanCallback)
            isScanning = false
            binding.btnScanBluetooth.text = "扫描蓝牙"
        }
    }

扫描和停止扫描时修改一下变量值并且改动按钮的文字以表示当前是否正在扫描中。

④ 执行扫描

执行扫描就很简单了,首先我们需要在MainActivity中创建扫描意图:

	//请求BLUETOOTH_SCAN权限意图
    private val requestBluetoothScan =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) {
                //进行扫描
                startScan()
            } else {
                showMsg("Android12中未获取此权限,则无法扫描蓝牙。")
            }
        }

这个意图我们将在点击扫描按钮的时候会用到,下面我们在initView中增加扫描按钮点击的代码:

		//扫描蓝牙
        binding.btnScanBluetooth.setOnClickListener {
            if (isAndroid12()) {
                if (hasPermission(Manifest.permission.BLUETOOTH_SCAN)) {
                    //扫描或者停止扫描
                    if (isScanning) stopScan() else startScan()
                } else {
                    //请求权限
                    requestBluetoothScan.launch(Manifest.permission.BLUETOOTH_SCAN)
                }
            }
        }

相对来说还是比较的简洁,其实还可以更简洁。我在扫描回调中打印了日志,如果有扫描到设备的话,就会有日志,下面我们扫描一下看看:

在这里插入图片描述

扫描启动了,但是没有设备被扫描到,可我附近明明有蓝牙设备正在广播,这是为什么呢?

⑤ 应用不推导物理位置

这个说起来就和之前的Android 6.0 至 Android 11.0中需要定位权限才能扫描有关系了,就是因为这个推导物理位置,手机是可以通过扫描到的设备知道设备的具体位置的,所以之前需要定位权限,那么现在我没有定位权限了,你扫不到设备就很离谱,怎么解决呢?

如果您的应用不推导物理位置,那么您可以坚定地断言您的应用绝不会使用蓝牙权限来推导物理位置。为此,请完成以下步骤:

将 android:usesPermissionFlags 属性添加到 BLUETOOTH_SCAN 权限声明,并将此属性的值设为 neverForLocation。

注意:如果 android:usesPermissionFlags 中包含 neverForLocation,则会从扫描结果中过滤出某些 BLE 信标。

这是官方的说明,操作起来很简单,如下图所示:

在这里插入图片描述

意思很明显,就是说你如果不需要推导物理地址,那么就设置一下这个权限的标识即可。下面我们再来运行一下:

在这里插入图片描述

设备就扫描到了,可以看到这里有设备的Mac地址,再点一下就可以停止扫描了。

不过我们这里是控制台显示了设备,并没有在页面显示设备,下面我们完成这一步。

五、页面显示扫描设备

显示蓝牙设备首先我们需要修改一下activity_main.xml布局,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_open_bluetooth"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="10dp"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:text="打开蓝牙"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_scan_bluetooth"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="10dp"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:text="扫描蓝牙"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_open_bluetooth" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_device"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="20dp"
        android:overScrollMode="never"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_scan_bluetooth" />

</androidx.constraintlayout.widget.ConstraintLayout>

① 蓝牙设备适配器

这个里的适配器使我们自己去写的,需要显示数据的,首先我们需要创建一个蓝牙图标,在drawable包下新建一个icon_bluetooth.xml,里面的代码如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:autoMirrored="true"
    android:tint="#000000"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">

    <path
        android:fillColor="@android:color/white"
        android:pathData="M14.24,12.01l2.32,2.32c0.28,-0.72 0.44,-1.51 0.44,-2.33 0,-0.82 -0.16,-1.59 -0.43,-2.31l-2.33,2.32zM19.53,6.71l-1.26,1.26c0.63,1.21 0.98,2.57 0.98,4.02s-0.36,2.82 -0.98,4.02l1.2,1.2c0.97,-1.54 1.54,-3.36 1.54,-5.31 -0.01,-1.89 -0.55,-3.67 -1.48,-5.19zM15.71,7.71L10,2L9,2v7.59L4.41,5 3,6.41 8.59,12 3,17.59 4.41,19 9,14.41L9,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM11,5.83l1.88,1.88L11,9.59L11,5.83zM12.88,16.29L11,18.17v-3.76l1.88,1.88z" />

</vector>

因为我们的设备需要显示信号强度,那么我们创建一个数据类,在com.llw.bluetooth包下新建一个MyDevice类,代码如下:

data class MyDevice(val device: BluetoothDevice, var rssi: Int)

然后我们构建适配器的item布局,在layout包下新建一个item_device.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="device"
            type="com.llw.bluetooth.MyDevice" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="70dp">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginStart="10dp"
            android:layout_marginTop="10dp"
            android:padding="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:class="lazy" data-srcCompat="@drawable/icon_bluetooth" />

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="10dp"
            android:text="@{device.device.name ?? `Unknown` }"
            android:textColor="@color/black"
            android:textSize="14sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toStartOf="@+id/tv_rssi"
            app:layout_constraintStart_toEndOf="@+id/imageView"
            app:layout_constraintTop_toTopOf="@+id/imageView" />

        <TextView
            android:id="@+id/tv_address"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="4dp"
            android:text="@{device.device.address}"
            android:textSize="12sp"
            app:layout_constraintBottom_toBottomOf="@+id/imageView"
            app:layout_constraintEnd_toStartOf="@+id/tv_rssi"
            app:layout_constraintStart_toEndOf="@+id/imageView" />

        <TextView
            android:id="@+id/tv_rssi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="10dp"
            android:text="@{device.rssi+`dBm`}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这里的布局数据采用了DataBinding。下面我们去写适配器,在com.llw.bluetooth包新建一个MyDeviceAdapter类,里面的代码如下:

class MyDeviceAdapter(data: MutableList<MyDevice>) :
    BaseQuickAdapter<MyDevice, BaseDataBindingHolder<ItemDeviceBinding>>(R.layout.item_device, data) {
    override fun convert(holder: BaseDataBindingHolder<ItemDeviceBinding>, item: MyDevice) {
        holder.dataBinding?.apply {
            device = item
            executePendingBindings()
        }
    }
}

这里就用到之前build.gradle中第三方依赖库的适配器,相当好用。下面我们回到MainActivity中。

② 显示列表设备

在MainActivity中创建两个变量:

	//设备列表
    private val deviceList = mutableListOf<MyDevice>()
    //适配器
    private lateinit var myDeviceAdapter: MyDeviceAdapter

这里我们需要思考一个问题,那就是列表设备的唯一性,因为蓝牙设备是一直广播的,所以我们扫描到的结果会有重复的设备,重复的设备有信号强度上的差异,这个地方我们要做的就是判断当前列表中是否有此设备,有就更新rssi,没有就添加,我们新增一个findDeviceIndex()函数,代码如下:

	private fun findDeviceIndex(scanDevice: MyDevice, deviceList: List<MyDevice>): Int {
        var index = 0
        for (device in deviceList) {
            if (scanDevice.device.address.equals(device.device.address)) return index
            index += 1
        }
        return -1
    }

下面我们再新增一个addDeviceList()函数,代码如下:

	private fun findDeviceIndex(scanDevice: MyDevice, deviceList: List<MyDevice>): Int {
        var index = 0
        for (device in deviceList) {
            if (scanDevice.device.address.equals(device.device.address)) return index
            index += 1
        }
        return -1
    }

最后我们在扫描回调中调用此方法:

在这里插入图片描述

最后别忘记了我们的适配器和列表都需要初始化的,我写在initView()函数中,如下图所示:

在这里插入图片描述

现在就可以运行了。

在这里插入图片描述

其实Android12蓝牙只有权限上要注意一下,虽然有三个动态权限,但是只要你同意了一个就都同意了,因为它们属于同一个权限组,所以如果你能确保当前拥有其中一个权限的话,蓝牙的操作就和之前一样的。不过还是有一些问题的,那就是在打开蓝牙之后要对变量进行赋值,如下图所示:

在这里插入图片描述

六、适配Android12.0以下设备

当前的代码我们在Android12上是没有问题了,但是Android12一下Android6.0以上还是扫描不到设备,因为需要定位权限,那么我们在AndroidManifest.xml中增加:

	<!--Android6-11 定位权限-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

然后我们回到MainActivity中,增加一个定位意图

	//请求定位权限意图
    private val requestLocation =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) {
                //扫描蓝牙
                startScan()
            } else {
                showMsg("Android12以下,6及以上需要定位权限才能扫描设备")
            }
        }

然后我们回到扫描按钮的点击事件。

在这里插入图片描述

下面我们在Android10.0上运行一下:

在这里插入图片描述

七、源码

如果你觉得代码对你有帮助的话,不妨Fork或者Star一下~
GitHub:Android12Bluetooth

到此这篇关于Android12 蓝牙适配的实现步骤的文章就介绍到这了,更多相关Android12 蓝牙适配内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android12 蓝牙适配的实现步骤

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Windows8下设置蓝牙配对的操作步骤

今天小编给大家介绍Windows7台式机设置蓝牙的详细步骤。具体如下:1、电脑右下角的显示隐藏图标上点击,选择蓝牙图标。2、在打开的蓝牙设置窗口,选项标签页中,将允许蓝牙设备查找这台电脑打勾选定,点击右下角的应用,然后点击“确定
2022-06-04

Android适配安卓6.0蓝牙通讯实现过程

事先说明: 安卓蓝牙需要定位权限申请,在安卓6.0需要用户手动确认权限后才能使用,各位可以自行查询资料实现,如果嫌麻烦,可以用第三方Bmob集成好的工具类进行实现,详细可以看http://blog.csdn.net/qq_30379689/
2022-06-06

ubuntu20.04配置mysql8.0的实现步骤

目录1 安装1.1 下载1.2 安装1.3 安装mysql Server1.4常用命令2 配置外网访问2.1 查看端口2.2修改配置文件2.3 修改root密码2.4修改用户安装过程询问一般 y 就可以了1 安装1.1 下载wget
2023-05-05

MyBatis实现配置加载的步骤

本文主要介绍了MyBatis实现配置加载的步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-19

Docker配置MySql环境的实现步骤

本指南介绍了在Docker中配置MySQL环境的完整步骤。从安装Docker到创建MySQL容器、连接到容器、创建数据库和用户、查看容器日志、备份数据、停止和删除容器,再到恢复数据,都有详细说明。通过遵循这些步骤,您可以轻松地为您的项目设置一个功能齐全的MySQL环境。
Docker配置MySql环境的实现步骤
2024-04-02

Nginx配置http和https的实现步骤

Nginx配置HTTP和HTTPS本指南介绍了使用Nginx配置HTTP和HTTPS连接的详细步骤。通过获取SSL证书并配置虚拟主机块,您可以启用HTTPS,从而确保数据安全和隐私。步骤包括:获取SSL证书配置Nginx虚拟主机设置SSL证书和密钥配置HTTPS重定向设置SSL参数(可选)通过遵循这些步骤并验证配置,您可以为您的网站创建安全可靠的连接。
Nginx配置http和https的实现步骤
2024-04-02

实现Flex配置的步骤是怎样的

今天就跟大家聊聊有关实现Flex配置的步骤是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。在多层式开发模型中,Flex应用属于表现层。Flex的语言和文件结构也试图把应用程序的
2023-06-17

vue实现移动端适方案的完整步骤

现在的手机五花八门,造就了移动端窗口分辨率繁多的局面,在不同分辨率的屏幕下保持与UI图一致的效果,就成了让前端不得不头疼的问题,下面这篇文章主要给大家介绍了vue实现移动端适方案的相关资料,需要的朋友可以参考下
2022-11-13

conda配置python虚拟环境的实现步骤

本文主要介绍了conda配置python虚拟环境的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-03-19

SpringBoot自动配置Quartz的实现步骤是什么

本篇内容介绍了“SpringBoot自动配置Quartz的实现步骤是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 依赖信息spri
2023-06-25

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录