java.lang.SecurityException:权限拒绝:尝试请求蓝牙权限时启动意图

问题描述 投票:0回答:1

我正在使用 Flutter android 插件,对 Android 开发环境不太熟悉。我面临着一个似乎“流行”的问题,但我尝试的所有解决方案都不起作用,而且我无法理解问题的根源。

问题是:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bluetooth_example/com.example.bluetooth.BluetoothPermissionActivity}: java.lang.SecurityException: Permission Denial: starting Intent { act=android.bluetooth.adapter.action.REQUEST_ENABLE cmp=com.android.settings/.bluetooth.RequestPermissionActivity } from ProcessRecord{e30ff3f 13434:com.example.bluetooth_example/u0a349} (pid=13434, uid=10349) requires android.permission.BLUETOOTH_CONNECT

据我所知,该问题与缺少

android.permission.BLUETOOTH_CONNECT
权限有关,应将其放在
AndroidManifest.xml
中。问题是我已经拥有那里的所有蓝牙权限。这是我的 AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.bluetooth">
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can strongly assert that your app
         doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application>
        <activity android:name="BluetoothPermissionActivity" android:exported="true" android:theme="@style/Theme.Transparent" />
    </application>
</manifest>

我认为我拥有所有必要的权限...活动

BluetoothPermissionActivity
是我创建的活动,要求用户启用蓝牙权限,就像android文档建议的那样。这是实现:

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.bluetooth.BluetoothAdapter
import androidx.activity.result.contract.ActivityResultContracts

internal const val ACTION_PERMISSIONS_GRANTED = "BluetoothPermission.permissions_granted"
internal const val ACTION_PERMISSIONS_DENIED = "BluetoothPermission.permissions_denied"

class BluetoothPermissionActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        val registerForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                sendBroadcast(Intent(ACTION_PERMISSIONS_GRANTED))
            } else {
                sendBroadcast(Intent(ACTION_PERMISSIONS_DENIED))
            }
        }

        registerForResult.launch(enableBtIntent)
    }
}

但是一旦我尝试启动

enableBtIntent
意图,就会抛出上面的错误。我尝试将
exported=true
添加到清单中的活动中,但效果不佳。我有点不知道这个问题的原因是什么,因为我拥有清单中的所有权限并且活动已导出(这似乎是此问题的 99% 的建议)。

更新:它似乎可以在具有版本<12. It seems something related with the newer Android versions.

的Android设备上运行
android android-permissions flutter-plugin
1个回答
0
投票

我对 Android 环境还没有信心,但我想我已经解决了上述问题。

registerForActivityResult(ActivityResultContracts.StartActivityForResult())
行并不请求许可,它正在尝试启动活动。我们需要先征求用户的许可。我将
BluetoothPermissionActivity
更改为:

internal const val ACTION_PERMISSIONS_GRANTED = "BluetoothPermission.permissions_granted"
internal const val ACTION_PERMISSIONS_DENIED = "BluetoothPermission.permissions_denied"

class BluetoothPermissionActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        when {
            checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED -> {
                sendBroadcast(Intent(ACTION_PERMISSIONS_GRANTED))
                finish()
            }
            else -> {
                requestPermissions(arrayOf(Manifest.permission.BLUETOOTH_CONNECT), 1)
            }
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            sendBroadcast(Intent(ACTION_PERMISSIONS_GRANTED))
            finish()
        } else {
            sendBroadcast(Intent(ACTION_PERMISSIONS_DENIED))
            finish()
        }
    }
}

它按预期工作。我希望这可以帮助面临类似问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.