Android12中蓝牙权限适配

文章详细介绍了在Android12中针对蓝牙权限的更新,包括AndroidManifest.xml中的配置变化,如新增的BLUETOOTH_SCAN、BLUETOOTH_ADVERTISE、BLUETOOTH_CONNECT权限。同时,文中提供了蓝牙状态监听的BroadcastReceiver实现,并展示了如何在代码中动态申请Android12的蓝牙权限。强调了在Android12中,不申请定位权限时需设置usesPermissionFlags为neverForLocation,否则可能无法搜索到设备。最后指出,无论在哪个Android版本,未开启蓝牙或缺少权限都将无法正常使用蓝牙功能。

AndroidManifest.xml

<!--maxSdkVersion=30适配到Android11 -->
<uses-permission
    android:name="android.permission.BLUETOOTH"
    android:maxSdkVersion="30" />
<uses-permission
    android:name="android.permission.BLUETOOTH_ADMIN"
    android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--Android12新增蓝牙权限 -->
<!-- Android 12在不申请定位权限时,必须加上android:usesPermissionFlags="neverForLocation",否则搜不到设备 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation"
        tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

代码

//获取蓝牙适配器
public static BluetoothAdapter mBluetoothAdapter = null;
    //蓝牙状态监听广播
    public class BlueToothReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                    switch (blueState) {
                        case BluetoothAdapter.STATE_TURNING_ON:
                            Log.e("onReceive", "---------蓝牙正在打开中");
                            break;
                        case BluetoothAdapter.STATE_ON:
                            Log.e("onReceive", "---------蓝牙已经打开");
                            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:
                            Log.e("onReceive", "---------蓝牙正在关闭中");
                            break;
                        case BluetoothAdapter.STATE_OFF:
                            Log.e("onReceive", "---------蓝牙已经关闭");
                            break;
                    }
                    break;
            }
        }
    }
    private IntentFilter makeFilter() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        return filter;
    }
    //Android12蓝牙权限申请
    private boolean bluePermission(){
    //compileSdkVersion项目中编译SDK版本大于30申请以下权限可使用
    //Manifest.permission.BLUETOOTH_SCAN、Manifest.permission.BLUETOOTH_ADVERTISE、Manifest.permission.BLUETOOTH_CONNECT
    //若小于30可以直接使用权限对应的字符串
        if (Build.VERSION.SDK_INT>30){
            if (ContextCompat.checkSelfPermission(this,
                    "android.permission.BLUETOOTH_SCAN")
                    != PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this,
                    "android.permission.BLUETOOTH_ADVERTISE")
                    != PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this,
                    "android.permission.BLUETOOTH_CONNECT")
                    != PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(this,new String[]{
                                "android.permission.BLUETOOTH_SCAN",
                                "android.permission.BLUETOOTH_ADVERTISE",
                                "android.permission.BLUETOOTH_CONNECT"}, 1);
                return false;
            }
        }
        return true;
    }
    private void openBlueTooth(){
        if (bluePermission())
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        else
            return;
        BlueToothReceiver btlr = new BlueToothReceiver();
        this.registerReceiver(btlr, makeFilter());
        if (!mBluetoothAdapter.isEnabled()) {// 判断是否打开蓝牙
            showHandlerToast("请先开启蓝牙!");
            //弹出对话框提示用户是后打开
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            //startActivityForResult(intent, SEARCH_CODE);
            // 不做提示,强行打开
            mBluetoothAdapter.enable();
        }
    }

说明:

必须按照这两步申请蓝牙权限,首先在androidManifest.xml中配置蓝牙权限,Android11及以下android.permission.BLUETOOTH、android.permission.BLUETOOTH_ADMIN申请这两个,Android12中蓝牙权限进行新增android.permission.BLUETOOTH_SCAN、android.permission.BLUETOOTH_ADVERTISE、android.permission.BLUETOOTH_CONNECT使用这三个;其次在代码中需要动态申请Android12的蓝牙权限,测试发现Android12中动态申请权限后则蓝牙直接开启,通过对蓝牙状态的监听获取蓝牙适配器:mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

注意:不管是Android12还是Android12以下不打开蓝牙都是无法获取蓝牙适配器:mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();打开蓝牙则可以获取到蓝牙适配器,但若没有申请蓝牙所需权限,蓝牙功能也是无法使用!!!二者缺一不可

<think>好的,我现在需要帮助用户解决在Android 14中适配蓝牙扫描和连接权限的问题。首先,我应该回顾一下Android权限的变化历史,尤其是从Android 12到现在的版本。记得在Android 12中,蓝牙权限有了较大的调整,比如引入了BLUETOOTH_SCAN和BLUETOOTH_CONNECT等运行时权限,替代了之前的ACCESS_FINE_LOCATION用于扫描。现在用户问的是Android 14,需要确认是否有新的变化。 首先,我应该查阅最新的Android 14开发者文档,看看官方有没有更新蓝牙相关的权限要求。可能需要检查以下内容: 1. **权限声明**:Android 12开始,扫描蓝牙设备需要BLUETOOTH_SCAN权限,连接需要BLUETOOTH_CONNECT,并且可能还需要声明NEARBY_DEVICES权限。在Android 14中,这些权限是否依然适用,或者有没有新增的权限? 2. **定位权限**:在Android 12之后,如果应用需要获取蓝牙设备的位置信息,可能仍然需要ACCESS_FINE_LOCATION权限,但普通扫描可能不需要了。但Android 14是否有进一步的变化?比如是否需要后台定位权限? 3. **后台扫描限制**:Android版本更新通常会加强对后台服务的限制,Android 14是否引入了新的限制,比如后台扫描需要额外的权限或限制? 4. **附近设备权限**:NEARBY_DEVICES权限Android 12引入,用于让应用在不请求位置权限的情况下访问附近的设备。这个在Android 14中是否仍然必要? 接下来,我需要整理这些信息,形成一个步骤指南。例如: - 在AndroidManifest.xml中声明必要的权限。 - 检查是否需要动态请求运行时权限。 - 处理Android 14中可能的权限变更,比如新的权限或旧权限的废弃。 - 适配后台扫描和连接的策略变化。 - 考虑目标SDK版本的影响,确保应用正确声明targetSdkVersion为34(对应Android 14)。 另外,可能需要提醒用户关于权限使用的用途声明,比如在Google Play商店中声明为什么需要这些权限,避免应用被拒绝。 还需要注意,如果应用在后台扫描蓝牙设备,Android 14可能要求更严格的权限,比如前台服务或者特殊许可,这需要检查最新的文档。 最后,应该提供代码示例,展示如何在代码中请求这些权限,并处理用户的授权结果。例如,使用ActivityResultContracts.RequestMultiplePermissions来处理BLUETOOTH_SCAN和BLUETOOTH_CONNECT的动态请求。 可能遇到的问题包括:用户没有授予权限时如何处理,兼容旧版本Android系统的策略,以及测试方法确保权限适配正确。此外,要确认在Android 14中,BLUETOOTH_ADMIN权限是否已经被完全废弃,或者仍有部分功能需要它。 总结步骤: 1. 声明所需权限BLUETOOTH_SCAN, BLUETOOTH_CONNECT, 可能还有NEARBY_DEVICES)。 2. 动态请求运行时权限。 3. 处理后台扫描的限制。 4. 更新目标SDK版本到34,并测试兼容性。 5. 在Play Console中声明权限用途。 需要确保所有信息都是基于最新的Android 14文档,避免过时的内容误导用户。如果官方文档没有特别提到变化,那么可能沿用Android 12和13的做法,但必须确认这一点。</think>### Android 14 蓝牙权限适配指南 #### 1. 权限声明 在 `AndroidManifest.xml` 中声明以下权限: ```xml <!-- 扫描蓝牙设备 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- 连接蓝牙设备 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 13+ 附近设备权限 --> <uses-permission android:name="android.permission.NEARBY_DEVICES" /> <!-- 仅当需要获取物理位置时才需要 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="33" /> ``` #### 2. 运行时权限请求 在代码中动态申请权限: ```kotlin val permissions = arrayOf( Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT ) val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { results -> if (results.all { it.value }) { // 权限已授予,开始扫描/连接 } } // 触发权限请求 requestPermissionLauncher.launch(permissions) ``` #### 3. Android 14 新增要求 1. **NEARBY_DEVICES权限自动授予** 当请求 `BLUETOOTH_SCAN` 时,系统会自动授予 `NEARBY_DEVICES` 权限[^1]。 2. **后台扫描限制** 如果应用在后台扫描设备,需声明 `android:usesPermissionFlags="neverForLocation"` 并确保不获取位置信息: ```xml <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> ``` 3. **权限用途声明** 在 Google Play 商店的元数据中需说明蓝牙权限用途: ``` 此权限用于扫描和连接附近的健身设备,以实现数据同步功能。 ``` #### 4. 完整代码示例 ```kotlin class BluetoothManager : AppCompatActivity() { private val bluetoothAdapter: BluetoothAdapter? by lazy { val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) checkPermissions() } private fun checkPermissions() { when { ContextCompat.checkSelfPermission( this, Manifest.permission.BLUETOOTH_SCAN ) == PackageManager.PERMISSION_GRANTED -> { startScan() } else -> { requestPermissions() } } } private fun startScan() { bluetoothAdapter?.bluetoothLeScanner?.startScan(scanCallback) } private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { // 处理扫描结果 } } } ``` #### 5. 兼容性处理 ```xml <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值