android - 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>
解决方案
推荐阅读
- spring - 弹簧靴和百里香叶
- python - .bat 批处理文件循环多个 python 文件并将输出与所需的输出文件进行比较
- python - 自定义数据集上的冻结模型推理标签
- clevermaps - 如何再次进入 CleverMaps 中的项目?
- function - 请您向我解释一下高阶函数的柯里化是如何工作的,尤其是下面的示例
- angular - 如果使用 ng-container,请在 mat-tab 中添加提示
- python - Python - 序列维度的问题
- hive - Trino Hive 连接器:如何启用管理员角色(系统角色)?
- java - 将不同的标题栏设置为 collapsingToolbarLayout
- azure - 如何在 DEV 中禁用 ADF 触发器,但使用 Azure DevOps CI/CD 管道在 PROD 中启用它们?