You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 12应用崩溃:请求启用蓝牙触发SecurityException

Android 12设备启动蓝牙权限崩溃问题

应用在Android 12设备上调用蓝牙开启Intent时崩溃,抛出如下异常:

Fatal Exception: java.lang.SecurityException
Permission Denial: starting Intent { act=android.bluetooth.adapter.action.REQUEST_ENABLE cmp=com.android.settings/.bluetooth.RequestPermissionActivity } from ProcessRecord{b25524d 23206:com.actofitSmartScale/u0a409} (pid=23206, uid=10409) requires android.permission.BLUETOOTH_CONNECT

尽管AndroidManifest.xml中已声明BLUETOOTH_CONNECT权限,仍出现此问题。以下是相关配置:

Gradle文件配置

compileSdkVersion 32
defaultConfig {
    applicationId "com"
    minSdkVersion 21
    targetSdkVersion 30
    versionCode 165
    versionName "7.0.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

    buildTypes {
        debug {
            versionNameSuffix ".debug"
            debuggable true
            applicationIdSuffix ".xxxx"
        }
        release {
            applicationIdSuffix ".xxxx"
            signingConfig signingConfigs.release
        }
    }
}

AndroidManifest.xml配置

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.XXXXX.XXXXX">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

<queries>
    <package android:name="com.google.android.apps.fitness" />
</queries>
<queries>
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
    </intent>
</queries>

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

<application
    android:name=".app.ApplicationClass"
    android:allowBackup="false"
    android:configChanges="orientation|screenSize|layoutDirection"
    android:icon="@mipmap/ic_smartscale_icon"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:networkSecurityConfig="@xml/network_security_config"
    android:requestLegacyExternalStorage="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:usesCleartextTraffic="true"
    tools:replace="android:allowBackup">


    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

    <service
        android:name="com.clevertap.android.sdk.pushnotification.fcm.FcmMessageListenerService"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>


    <activity
        android:name=".app.BaseActivity"
        android:exported="true"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustPan">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
            <action android:name="android.intent.action.VIEW" />
        </intent-filter>
        <nav-graph android:value="@navigation/nav_app" />
    </activity>

    <activity
        android:name=".share.ShareActivity"
        android:exported="true"
        android:screenOrientation="landscape">
        <intent-filter>
            <action android:name="com.actofit.share.smartscale" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.clevertap.android.sdk.InAppNotificationActivity"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    <meta-data
        android:name="CLEVERTAP_ACCOUNT_ID"
        android:value="8R7-549-KR5Z" />
    <meta-data
        android:name="CLEVERTAP_TOKEN"
        android:value="c45-a2b" />
    <meta-data
        android:name="CLEVERTAP_USE_GOOGLE_AD_ID"
        android:value="1" />
    <meta-data
        android:name="FCM_SENDER_ID"
        android:value="948450444651" />

    <service
        android:name="com.qingniu.qnble.scanner.BleScanService"
        android:permission="android.permission.BIND_JOB_SERVICE" />
    <service
        android:name="com.qingniu.scale.measure.ble.ScaleBleService"
        android:permission="android.permission.BIND_JOB_SERVICE" />
    <service
        android:name="com.qingniu.scale.measure.broadcast.ScaleBroadcastService"
        android:permission="android.permission.BIND_JOB_SERVICE" />
    <service
        android:name="com.qingniu.scale.wsp.ble.ScaleWspBleService"
        android:permission="android.permission.BIND_JOB_SERVICE" />
    <service
        android:name="com.qingniu.scale.measure.broadcast.ScaleFoodBroadcastService"
        android:permission="android.permission.BIND_JOB_SERVICE" />

    <service
        android:name=".biosense.BLeService"
        android:exported="false" />
    <service
        android:name=".util.fcm.FcmMessageListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <receiver
        android:name=".util.bluetooth.BluetoothBroadcastReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
        </intent-filter>
    </receiver>

    <activity
        android:name="com.actofit.smartscale.bot.activity.ChatBotActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.actofit.smartscale.payment.MakePaymentActivity"
        android:screenOrientation="portrait" />

    <activity
        android:name="com.actofit.smartscale.share_report.ShareReportActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.actofit.smartscale.dite.ActivitySearchFood"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.actofit.smartscale.dite.ActivityFoodInfo"
        android:screenOrientation="portrait" />
    <activity
        android:name=".custom_webview.customCrome.WebviewActivity"
        android:screenOrientation="portrait" />

    <activity
        android:name=".kitchin_scale.KitchinScaleTakeReadingActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.actofit.smartscale.offline_support.QuestionActivity"
        android:exported="true" />

    <activity
        android:name="com.actofit.smartscale.settings.GoalActivity"
        android:exported="true" />
    <activity
        android:name="com.actofit.smartscale.home.LogActivity"
        android:exported="true" />

    <activity
        android:name="com.actofit.smartscale.workout.OnBoardingActivity"
        android:configChanges="keyboardHidden|orientation|screenSize" />
    <activity
        android:name="com.actofit.smartscale.workout.GuidedWorkoutActivity"
        android:exported="true" />

    <activity
        android:name="com.actofit.smartscale.workout.RatingActivity"
        android:exported="true" />


    <meta-data
        android:name="CLEVERTAP_BACKGROUND_SYNC"
        android:value="1" />
    <receiver
        android:name=".util.fcm.NotificationBroadcastReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <action android:name="android.service.notification.NotificationListenerService" />
        </intent-filter>
    </receiver>
</application>
</manifest>

解决方案

1. 动态申请BLUETOOTH_CONNECT权限

Android 12(API 31及以上)将BLUETOOTH_CONNECT列为危险权限,仅在Manifest中声明无法生效,必须在代码中动态申请,且要在调用蓝牙开启Intent之前完成权限校验。

示例代码:

private static final int REQUEST_BLUETOOTH_CONNECT = 100;
private static final int REQUEST_ENABLE_BT = 101;

// 检查并申请蓝牙连接权限
private void checkBluetoothConnectPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.BLUETOOTH_CONNECT},
                    REQUEST_BLUETOOTH_CONNECT);
            return;
        }
    }
    // 权限已获取,启动蓝牙开启请求
    startBluetoothEnableIntent();
}

// 启动蓝牙开启Intent
private void startBluetoothEnableIntent() {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_BLUETOOTH_CONNECT) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            startBluetoothEnableIntent();
        } else {
            // 权限被拒绝,提示用户需要该权限才能使用蓝牙功能
            Toast.makeText(this, "需要蓝牙连接权限才能开启蓝牙", Toast.LENGTH_SHORT).show();
        }
    }
}

2. 升级targetSdkVersion至31+

当前项目targetSdkVersion为30,虽然Android 12设备会向下兼容,但升级到31或更高版本能更好地适配Android 12的权限规则,避免潜在的兼容性问题。修改Gradle配置:

defaultConfig {
    // ...其他配置
    targetSdkVersion 31 // 或更高版本
}

3. 确认权限申请时机

确保在任何调用ACTION_REQUEST_ENABLE Intent的代码路径前,都先执行权限检查逻辑,不要遗漏任何场景。


内容的提问来源于stack exchange,提问作者Rohit Barge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:24:24