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

Android Studio API32下requestPermissions无权限弹窗问题

问题根因
  • 核心错误:尝试直接申请NEARBY_DEVICES权限组。Android系统不支持开发者直接申请权限组,权限组仅用于系统在设置页归类展示权限,只能申请组内的具体运行时权限,传入权限组发起申请会被系统直接拦截,不弹出任何提示
  • Manifest文件存在语法错误:权限声明块末尾多了一行无标签包裹的纯文本"android.permission-group.NEARBY_DEVICES",MainActivity节点多写了一个多余的>闭合尖括号,会导致Manifest解析异常,所有权限声明失效
  • 权限申请逻辑不符合版本规则:Android 12(API 31)及以上版本中,旧版BLUETOOTH、BLUETOOTH_ADMIN属于安装时自动授予的普通权限,不需要运行时申请;同时ACCESS_BACKGROUND_LOCATION后台位置权限从Android 10开始就不允许和其他前台权限一起申请,混合申请会被系统直接忽略
  • 无效冗余:申请的权限列表中重复写入了两次BLUETOOTH_CONNECT,属于无效写法
修复方案

1. 修正AndroidManifest.xml配置

删除无效内容、修正语法错误,针对不同版本做权限适配:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.navigation" >

    <!-- Android 11及以下版本的旧蓝牙权限,高版本不需要 -->
    <uses-permission android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" />
    <!-- Android12+ 蓝牙运行时权限,不需要通过蓝牙推导位置的话加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" />
    <!-- Android11及以下扫描蓝牙需要位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
    <!-- 移除NEARBY_DEVICES权限组的错误声明,移除孤立的纯文本行 -->

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

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Navigation"
        tools:targetApi="32" >
        <activity
            android:name=".DeviceScanActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop" >
            <!-- 移除这里多余的>符号 -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2. 重写权限申请逻辑

按系统版本拆分需要申请的权限列表,分开申请前台权限和后台位置权限,移除重复、无效的权限项:

private static final int REQUEST_CODE_NEARBY_PERMS = 1;
private static final int REQUEST_CODE_BACKGROUND_LOC = 2;

public void getPermissions(){
    List<String> needRequest = new ArrayList<>();
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        // Android12+ 只需要申请新的蓝牙相关运行时权限
        if (checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.BLUETOOTH_SCAN);
        }
        if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.BLUETOOTH_CONNECT);
        }
        if (checkSelfPermission(Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.BLUETOOTH_ADVERTISE);
        }
        if (checkSelfPermission(Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.ACTIVITY_RECOGNITION);
        }
    } else {
        // Android11及以下只需要申请位置权限即可扫描蓝牙
        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            needRequest.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        }
    }

    if (!needRequest.isEmpty()) {
        requestPermissions(needRequest.toArray(new String[0]), REQUEST_CODE_NEARBY_PERMS);
        return;
    }

    // 等前面的前台权限全部授予后,再单独申请后台位置权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q 
        && checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE_BACKGROUND_LOC);
    }
}

3. 调整调用时机

不要在Activity未完全进入前台时调用权限申请方法,比如不要直接在onCreate生命周期第一行调用,建议放在用户点击「扫描蓝牙设备」这类交互按钮的点击事件中触发,避免系统拦截权限弹窗。

内容的提问来源于stack exchange,提问作者Ali Abdullah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:24:10