You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:44:53