Android APK如何正确建立USB连接?权限与连接空值问题求助
USB Host相机连接问题
我正在尝试让Android应用中USB连接的相机正常运行,已遵循Android官方USB Host开发文档指引,但遇到两个问题:
- 权限请求系统对话框从未弹出,发起权限请求后始终被拒绝;
UsbDeviceConnection始终为空,虽能获取设备的接口数量、端点、设备名称等信息,但无法建立有效连接。
代码实现
MainActivity.java
package com.example.usbdev; import android.app.PendingIntent; import android.content.BroadcastReceiver; 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.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.util.HashMap; public class MainActivity extends AppCompatActivity { public class UsbPermissionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); textView.append("\nAction: " + action); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ textView.append("\nPermission granted"); } } else { textView.append("\nPermission denied"); } UsbDeviceConnection connection = usbManager.openDevice(device); if (connection != null) { textView.append("\nconnection ok"); } else { textView.append("\nconnection null"); } } } } } private TextView textView; private Button button; private UsbManager usbManager; private UsbDevice device; private PendingIntent permissionIntent; private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private Byte[] bytes; private static int TIMEOUT = 0; private boolean forceClaim = true; private final BroadcastReceiver usbReceiver = new UsbPermissionReceiver(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.textView); button = findViewById(R.id.button); permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { registerReceiver(usbReceiver, filter, Context.RECEIVER_EXPORTED); } button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { executeButton(); } }); usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList(); device = null; for (UsbDevice d : deviceList.values()) { device = d; break; // Exit the loop after finding the first device } if (device != null) { // If a device is found, request permission for it usbManager.requestPermission(device, permissionIntent); } } private void executeButton() { usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList(); device = null; for (UsbDevice d : deviceList.values()) { device = d; break; // Exit the loop after finding the first device } if (device != null) { // If a device is found, request permission for it textView.append("\nDevice: "+device.getDeviceName()); usbManager.requestPermission(device, permissionIntent); } else { // No USB devices connected textView.append("\nNo connected devices"); } } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(usbReceiver); } }
Manifest配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.usbdev"> <uses-feature android:name="android.hardware.usb.host" android:required="true"/> <uses-permission android:name="android.permission.USB_PERMISSION" android:required="true"/> <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/AppTheme"> <receiver android:name=".MainActivity$UsbPermissionReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.example.usbdev.USB_PERMISSION" /> </intent-filter> </receiver> <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> </activity> </application> </manifest>
运行截图

问题解决方法
1. 权限请求对话框不弹出/始终被拒绝的问题
- ACTION_USB_PERMISSION 常量不一致:代码中定义的权限Action是
com.android.example.USB_PERMISSION,但Manifest里接收器的Action是com.example.usbdev.USB_PERMISSION,两者必须完全匹配。修改代码中的常量:private static final String ACTION_USB_PERMISSION = "com.example.usbdev.USB_PERMISSION"; - PendingIntent 标记兼容问题:Android 12及以上使用
FLAG_IMMUTABLE可能导致权限弹窗无法触发,改为兼容标记:int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0; permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), flags); - 接收器注册逻辑不全:当前仅在Android 13+注册接收器,低版本系统会遗漏,补充完整注册逻辑:
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { registerReceiver(usbReceiver, filter, Context.RECEIVER_EXPORTED); } else { registerReceiver(usbReceiver, filter); }
2. UsbDeviceConnection 为空的问题
- 权限未授予就尝试连接:必须在权限确认授予后再调用
openDevice,修改接收器逻辑:if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ textView.append("\nPermission granted"); UsbDeviceConnection connection = usbManager.openDevice(device); if (connection != null) { textView.append("\nconnection ok"); } else { textView.append("\nconnection null"); } } } else { textView.append("\nPermission denied"); } - 设备被占用检查:确认没有其他应用正在使用该USB相机,必要时重启设备后测试。
- 设备接口权限验证:部分USB相机需要特定接口权限,确认设备支持Host模式,且应用有权访问对应接口。
内容的提问来源于stack exchange,提问作者Luiz Fernando Puttow Southier
相关产品推荐
相关产品推荐

