首页 > 解决方案 > Android SDK 28:无法获得访问 uvc usb 摄像头的 usbhost 权限

问题描述

我无法获得外部 USB 设备(uvc 摄像头)的 USB 主机权限。

usbmanager.requestPermission(device, pendingPermissionIntent)

返回 false 而不向用户显示任何意图。

代码适用于 sdk 27​​,但如果 sdk >= 28 则不起作用。

我还检查了相机权限,他们正在工作。

我正在使用 Oneplus 6t(stock os Android 10 进行测试)和 Android Studio 进行编译。

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ContentValues.TAG
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button


import android.Manifest
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

const val PERMISSION_REQUEST_CAMERA = 0
private const val ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"

class MainActivity : AppCompatActivity() {

    private var permissionIntent: PendingIntent? = null
    private lateinit var manager:UsbManager

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        manager = getSystemService(Context.USB_SERVICE) as UsbManager
        permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE)
        val filter = IntentFilter(ACTION_USB_PERMISSION)
        registerReceiver(usbReceiver, filter)

        val cameraButton = findViewById<Button>(R.id.cameraButton)
        val usbButton = findViewById<Button>(R.id.usbButton)

        cameraButton.setOnClickListener {
            checkCameraPermission()
        }

        usbButton.setOnClickListener {
            Log.d(TAG, "requesting permission USB")
            val deviceList: HashMap<String, UsbDevice> = manager.deviceList
            deviceList.values.forEach { device ->
                Log.d(TAG, "checking permission for device: $device")
                checkPermission(device)
            }
        }
    }


    @Synchronized
    fun checkPermission(device: UsbDevice?): Boolean {
        //  if (DEBUG) Log.v(TAG, "requestPermission:device=" + device);
        var result = false
        if (manager.hasPermission(device)){
            Log.v(TAG, "usb permission already there" )
            result = true
        }
        else{
            Log.v(TAG, "request Permission for usb device")
            manager.requestPermission(device, permissionIntent)

        }
        return result
    }


    private val usbReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (ACTION_USB_PERMISSION == intent.action) {
                synchronized(this) {
                    val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        Log.d(TAG, "permission granted for usb device ")
                        device?.apply {
                            //call method to set up device communication
                        }
                    } else {
                        Log.d(TAG, "permission denied for usb device ")
                    }
                }
            }
        }
    }

    private fun checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
            Log.d(TAG, "camera permission already granted")
        } else {
            Log.d(TAG, "camera Permission is missing and must be requested.")
            ActivityCompat.requestPermissions(this,arrayOf(Manifest.permission.CAMERA),PERMISSION_REQUEST_CAMERA)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSION_REQUEST_CAMERA)  {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "camera Permission Granted")
            }else{
                Log.d(TAG, "camera Permission Denied")
            }
        }
    }

}

我的清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.test">
    <uses-feature android:name="android.hardware.usb.host" />
    <uses-feature android:name="android.hardware.camera"
        android:required="true" />
    <uses-permission android:name="android.permission.CAMERA"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Test">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>
    </application>

</manifest>

设备过滤器文件

<?xml version="1.0" encoding="utf-8"?>
<usb>
    <usb-device class="239" subclass="2" /> <!-- all device of UVC -->
</usb>

标签: androidusb-camerausb-hostcontrolleroneplus6t

解决方案


推荐阅读