请求权限导致Android应用启动后无报错直接崩溃问题排查
应用发起权限请求时崩溃关闭问题排查
问题现象
- 应用启动后调用权限请求代码时直接关闭,无任何错误提示
- 注释掉
ActivityCompat.requestPermissions(this, permissions, REQUEST_MICROPHONE);后,应用可正常启动 - 需求权限:蓝牙相关权限、数据访问权限
问题相关代码
private static final int REQUEST_MICROPHONE = 1; private void askPermissions(){ String[] permissions = {Manifest.permission.RECORD_AUDIO, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT}; if (!hasPermissions(permissions)) { ActivityCompat.requestPermissions(this, permissions, REQUEST_MICROPHONE); } } private boolean hasPermissions(String[] permissions) { if(permissions != null){ for(String perm : permissions){ if(ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) return false; }} return true; }
Manifest配置文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <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.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- 仅向支持BLE的设备提供应用时添加以下配置 --> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:configChanges="orientation|screenSize" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:screenOrientation="portrait" android:theme="@style/Theme.myapp"> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/Theme.myapp.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
排查与修复方案
1. 拆分跨组权限请求
Android 11(API 30)开始限制单次权限请求的分组范围,你当前的请求同时包含麦克风、蓝牙、位置、存储4个权限组,跨组请求会触发系统异常。需分批次申请:
// 请求码常量 private static final int REQUEST_MICROPHONE = 1; private static final int REQUEST_BLUETOOTH_LOCATION = 2; private static final int REQUEST_STORAGE = 3; // 先申请麦克风权限 private void askMicPermission() { String[] micPerms = {Manifest.permission.RECORD_AUDIO}; if (ContextCompat.checkSelfPermission(this, micPerms[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, micPerms, REQUEST_MICROPHONE); } else { askBluetoothAndLocationPermissions(); } } // 再申请蓝牙+位置权限 private void askBluetoothAndLocationPermissions() { String[] btLocPerms = {Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT}; if (!hasPermissions(btLocPerms)) { ActivityCompat.requestPermissions(this, btLocPerms, REQUEST_BLUETOOTH_LOCATION); } else { askStoragePermission(); } } // 最后申请存储权限 private void askStoragePermission() { String[] storagePerm = {Manifest.permission.READ_EXTERNAL_STORAGE}; if (ContextCompat.checkSelfPermission(this, storagePerm[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, storagePerm, REQUEST_STORAGE); } }
2. 修正蓝牙权限声明
针对API 30,BLUETOOTH_SCAN需添加权限标记(若无需通过蓝牙获取位置),否则会和位置权限冲突:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
3. 规范权限请求时机
确保askPermissions()在Activity的onCreate()或onStart()方法中调用,避免在Activity未完全初始化时触发请求。
4. 添加权限回调处理
重写权限申请结果回调,确保流程连贯,避免潜在异常:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_MICROPHONE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { askBluetoothAndLocationPermissions(); } break; case REQUEST_BLUETOOTH_LOCATION: boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { askStoragePermission(); } break; case REQUEST_STORAGE: // 处理存储权限申请结果 break; } }
内容的提问来源于stack exchange,提问作者xikov
相关产品推荐
相关产品推荐

