绕过android usb主机权限确认对话框

Posted

技术标签:

【中文标题】绕过android usb主机权限确认对话框【英文标题】:bypass android usb host permission confirmation dialog 【发布时间】:2012-11-23 11:26:21 【问题描述】:

我想在工业界使用android

我可以使用 slickdevlabs.com 库毫无问题地连接到 Profilic 和 Ftdi USB 到串行芯片。

应用程序有一个服务,它在启动时启动,连接到 USB 串行端口并做其他事情。

我的问题是主机设备与用户没有任何交互,

所以当 android 询问时

Allow the app "MyAPP" to access the USB device ?
[checkmark]Use by default for this USB device
Cancel            OK

没有人点击ok。

即使我检查了默认使用...复选框,如果我重新插入 USB 或重新启动主机设备,它会在下次启动时再次询问。

我以超级用户模式运行服务和应用程序,但没有区别,它再次询问。

我添加了意图过滤器但没有区别,它每次都会问我。

        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
        </intent-filter>

        <meta-data
            android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
            android:resource="@xml/device_filter" />
        <meta-data
            android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
            android:resource="@xml/device_filter" />

任何意见如何绕过或禁用它?

我有 root 和 SU 访问权限。

【问题讨论】:

这是可能的解决方案吗? – ***.com/a/15151075/1454514 【参考方案1】:

解决方案是使用意图过滤器并将android:directBootAware="true" 属性添加到关联的活动中,以便在启动/重新启动后正确接收USB_DEVICE_ATTACHED 事件。重要的是不要在代码中请求USB 设备权限,只使用意图过滤器,如下所示:

<manifest>
    <uses-feature android:name="android.hardware.usb.host" />
    <activity
        ...
        android:directBootAware="true">

        <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>
</manifest>

使用 device_filter XML 资源文件类似于:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="1234" product-id="5678" />
</resources>

【讨论】:

谢谢!这是截至 2020 年迄今为止最简单、最快的解决方案。我仍然看到的一个问题是设备在拔出/重新插入后不可用,尽管这对我的项目来说并不那么重要。 它不起作用,我使用的是 sdk 21。【参考方案2】:

我认为提前将您正在使用的配件列入白名单将是最好的解决方案。 为此,您需要添加文件 usb_device_manager.xml 在这个位置 /数据/系统/用户/0 // 注意 0 是用户 ID,如果你没有在 Android 中添加更多用户,但如果你相应地更改了这个 ID,它可能会是 0

这是文件的外观:

<settings>
<preference package="<PACKAGE NAME OF APP YOU WANT TO START ON CONNECTIONCTION>">
    <usb-accessory manufacturer="<NAME OF MANUFECTURER LIKE ONE REGISTERED IN meta-data in the manifest>" model="<MODEL NAME LIKE ONE REGISTERED IN meta-data in the manifest>" version="<VERSION LIKE ONE REGISTERED IN meta-data in the manifest>" />
</preference>

对于这样的板子http://www.embeddedartists.com/products/app/aoa_kit.php 它是:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<settings>
<preference package="com.embeddedartists.aoa">
    <usb-accessory manufacturer="Embedded Artists AB" model="AOA Board - Basic" version="1.0" />
</preference>

【讨论】:

它实际上在重启时也被清除了。您需要设置一些东西,在启动时将 xml 文件复制到正确的目录。 model?那是什么? UsbDevice 类可以给我们产品名称、设备名称、制造商名称等。 “productName”是否等于“model”? NAME LIKE ONE REGISTERED IN meta-data in the manifest 那是什么?你在说什么?在哪里注册?哪个清单? 为什么你打开&lt;settings&gt;标签却不关闭它? @user924 它只是在答案中丢失,应该关闭。由于占位符,无论如何都不能复制粘贴。不幸的是,我无法解决这个问题,因为 *** 上的代码编辑器不会呈现它,但是当我尝试编辑它时它就在那里..【参考方案3】:

@d_d_t aswer 很棒,但它不适用于 Android > 4.2.2。使用这个接口:

public interface IUsbManager extends android.os.IInterface

/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.hardware.usb.IUsbManager 
    private static final java.lang.String DESCRIPTOR = "android.hardware.usb.IUsbManager";

    /** Construct the stub at attach it to the interface. */
    public Stub()         
        throw new RuntimeException( "Stub!" );
    

    /**
     * Cast an IBinder object into an android.hardware.usb.IUsbManager
     * interface, generating a proxy if needed.
     */
    public static android.hardware.usb.IUsbManager asInterface( android.os.IBinder obj) 
        throw new RuntimeException( "Stub!" );
    

    @Override
    public android.os.IBinder asBinder() 
        throw new RuntimeException( "Stub!" );
    

    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException 
        throw new RuntimeException( "Stub!" );
    

    static final int TRANSACTION_getDeviceList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_openDevice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_getCurrentAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    static final int TRANSACTION_openAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
    static final int TRANSACTION_setDevicePackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
    static final int TRANSACTION_setAccessoryPackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
    static final int TRANSACTION_hasDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
    static final int TRANSACTION_hasAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
    static final int TRANSACTION_requestDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
    static final int TRANSACTION_requestAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
    static final int TRANSACTION_grantDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
    static final int TRANSACTION_grantAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
    static final int TRANSACTION_hasDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);
    static final int TRANSACTION_clearDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);
    static final int TRANSACTION_setCurrentFunction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);
    static final int TRANSACTION_setMassStorageBackingFile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);
    static final int TRANSACTION_allowUsbDebugging = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16);
    static final int TRANSACTION_denyUsbDebugging = (android.os.IBinder.FIRST_CALL_TRANSACTION + 17);


/* Returns a list of all currently attached USB devices */
public void getDeviceList(android.os.Bundle devices)
        throws android.os.RemoteException;

/*
 * Returns a file descriptor for communicating with the USB device. The
 * native fd can be passed to usb_device_new() in libusbhost.
 */
public android.os.ParcelFileDescriptor openDevice(
        java.lang.String deviceName) throws android.os.RemoteException;

/* Returns the currently attached USB accessory */
public android.hardware.usb.UsbAccessory getCurrentAccessory()
        throws android.os.RemoteException;

/*
 * Returns a file descriptor for communicating with the USB accessory. This
 * file descriptor can be used with standard Java file operations.
 */
public android.os.ParcelFileDescriptor openAccessory(
        android.hardware.usb.UsbAccessory accessory)
        throws android.os.RemoteException;

/*
 * Sets the default package for a USB device (or clears it if the package
 * name is null)
 */
public void setDevicePackage(android.hardware.usb.UsbDevice device,
        java.lang.String packageName, int userId)
        throws android.os.RemoteException;

/*
 * Sets the default package for a USB accessory (or clears it if the package
 * name is null)
 */
public void setAccessoryPackage(
        android.hardware.usb.UsbAccessory accessory,
        java.lang.String packageName, int userId)
        throws android.os.RemoteException;

/* Returns true if the caller has permission to access the device. */
public boolean hasDevicePermission(android.hardware.usb.UsbDevice device)
        throws android.os.RemoteException;

/* Returns true if the caller has permission to access the accessory. */
public boolean hasAccessoryPermission(
        android.hardware.usb.UsbAccessory accessory)
        throws android.os.RemoteException;

/*
 * Requests permission for the given package to access the device. Will
 * display a system dialog to query the user if permission had not already
 * been given.
 */
public void requestDevicePermission(android.hardware.usb.UsbDevice device,
        java.lang.String packageName, android.app.PendingIntent pi)
        throws android.os.RemoteException;

/*
 * Requests permission for the given package to access the accessory. Will
 * display a system dialog to query the user if permission had not already
 * been given. Result is returned via pi.
 */
public void requestAccessoryPermission(
        android.hardware.usb.UsbAccessory accessory,
        java.lang.String packageName, android.app.PendingIntent pi)
        throws android.os.RemoteException;

/* Grants permission for the given UID to access the device */
public void grantDevicePermission(android.hardware.usb.UsbDevice device,
        int uid) throws android.os.RemoteException;

/* Grants permission for the given UID to access the accessory */
public void grantAccessoryPermission(
        android.hardware.usb.UsbAccessory accessory, int uid)
        throws android.os.RemoteException;

/*
 * Returns true if the USB manager has default preferences or permissions
 * for the package
 */
public boolean hasDefaults(java.lang.String packageName, int userId)
        throws android.os.RemoteException;

/* Clears default preferences and permissions for the package */
public void clearDefaults(java.lang.String packageName, int userId)
        throws android.os.RemoteException;

/* Sets the current USB function. */
public void setCurrentFunction(java.lang.String function,
        boolean makeDefault) throws android.os.RemoteException;

/* Sets the file path for USB mass storage backing file. */
public void setMassStorageBackingFile(java.lang.String path)
        throws android.os.RemoteException;

/*
 * Allow USB debugging from the attached host. If alwaysAllow is true, add
 * the the public key to list of host keys that the user has approved.
 */
public void allowUsbDebugging(boolean alwaysAllow,
        java.lang.String publicKey) throws android.os.RemoteException;

/* Deny USB debugging from the attached host */
public void denyUsbDebugging() throws android.os.RemoteException;

并修改添加用户id的代码:

...
service.setDevicePackage( usbDevice, YOUR_APP_PACKAGE_NAMESPACE, ai.uid ); 
....

【讨论】:

感谢您的信息。我看到您已共享 IUsbManager.java 接口代码。ServiceManager.java 的代码如何。4.2.2 的代码也不同吗?另外,即使设备重启/应用程序升级,usb权限弹出窗口也会出现吗? 在某些 Android 9 设备(例如 Xiaomi MI A2 Lite)上失败:java.lang.NoSuchMethodError: No interface method grantDevicePermission(Landroid/hardware/usb/UsbDevice;I)V in class Landroid/hardware/usb/IUsbManager; or its super classes (declaration of 'android.hardware.usb.IUsbManager' appears in /system/framework/framework.jar) 它似乎在 Android 9 上根本不起作用,不仅仅是某些设备 找到适用于 Android 9 的解决方案 ***.com/a/57622623/7767664【参考方案4】:

如果您可以访问 Android 源代码,这里是您需要禁用权限对话框的代码

https://gitlab.tubit.tu-berlin.de/justus.beyer/streamagame_platform_frameworks_base/commit/e97b62ed0d4050acacbf54781435686ea28edd73

上面的代码更新创建了一个您可以使用的配置选项,或者您可以使用值 true 代替 mDisablePermissionDialogs 对其进行硬编码以禁用权限对话框。

services/usb/java/com/android/server/usb/UsbSettingsManager.java

【讨论】:

没有人可以访问小米或三星固件源代码 我想不是,他们不是唯一使用开源 Android 操作系统的人【参考方案5】:

我遇到了同样的问题,每次插入 USB 电缆时都会出现权限弹出窗口,为了解决这个问题,我只是在清单中添加了过滤器以及 VID 和 PID 的 xml 文件,只需确保您已设置 USB 设备过滤如上面的 SO 链接中所建议的或此处记录的那样,您输入了良好的 VID 和 PID。这是我的问题,我没有把与我的设备匹配的 VID 和 PID

【讨论】:

重启后仍需要再次请求,intent filters 仅对当前启动会话有帮助【参考方案6】:

第一次需要确认的时候,可以选择“always”,这样即使Android设备掉电,再上电,你的app仍然有权限访问USB2Serial。只是说,只有一次确认!

【讨论】:

这是一个低质量的答案【参考方案7】:

我在弹出窗口中遇到了同样的问题,没有人可以点击它。 但我找到了一个不同的解决方案(针对有根设备)。 弹出窗口由 android 在类 UsbPermissionActivity 中生成(并且 UsbPermissionActivity 由 UsbSettingsManager 启动)。查看 Android 源代码以了解发生了什么。 这里的好处是,我们可以操纵 UsbPermissionActivity 的字节码来接受所有的 UsbDevices。您需要 Smali/Baksmali 工具来执行此操作。 https://code.google.com/p/smali/

    在您的设备上找到文件 SystemUI.apk 使用adb pull path/to/SystemUI.apk 将其复制到您的计算机上 解压apk 用java -jar baksmali.jar classes.dex反汇编classes.dex文件

    找到文件 UsbPermissionActivity 并在其中找到显示的行

    invoke-virtual p0, Lcom/android/systemui/usb/UsbPermissionActivity;-&gt;setupAlert()V

    通过注释掉它并添加两个新行来更改它

#invoke-virtual p0, Lcom/android/systemui/usb/UsbPermissionActivity;->setupAlert()V const/4 v0, 0x1 iput-boolean v0, p0, Lcom/android/systemui/usb/UsbPermissionActivity;->mPermissionGranted:Z invoke-virtual p0, Lcom/android/systemui/usb/UsbPermissionActivity;->finish()V

    java -jar smali.jar -o classes.dex out组装它 替换原来的 classes.dex 并将所有内容再次压缩到 SystemUI.apk 将您设备上的原始 SystemUI.apk 替换为 adb push services.jar path/to/SystemUI.apk 或者如果这不适用于文件管理器 ap

【讨论】:

我刚刚试了一下,它似乎也损坏了设备上的其他一些东西。 SystemUI 在/system/priv-app 下。这是 Android 4.4.2 。 它适用于 FTDI 权限,另一个缺少的步骤是在重新安装时在 SystemUI 上执行 chmod,apk。 效果很好! Smali/Baksmali 移至 github.com/JesusFreke/smali,在 Smali/Baksmali 2.2 中,命令已更改为 java -jar baksmali.jar d classes.dexjava -jar smali.jar a -o classes.dex out 找到适用于 Android 9 的解决方案 ***.com/a/57622623/7767664【参考方案8】:

如果你有编译android系统的选项,那么没有什么是你做不到的。

你可以添加

public void onStart() 
    super.onStart();
    mPermissionGranted = true;

    finish();

到frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java

绕过权限确认弹出窗口。

【讨论】:

感谢您,为我指明了正确的方向。阅读源代码然后发现在 frameworks/base/core/res/res/values/config.xml 中有一个名为 config_disableUsbPermissionDialogs 的配置 @RickSanchez - 如何更新 config.xml 文件以使用新值? 在AOSP树中修改,再次编译/刷入镜像。 @RickSanchez 好吧,您无法将 AOSP 编译后的映像安装到任何手机(例如最新的三星) @RickSanchez 刷新了整个系统映像 OMG。为什么不能自动。毕竟 GOOGLE ANDROID 我为您的安全设备付费!【参考方案9】:

我知道有点晚了,但还是……

我遇到了同样的问题,我想我已经设法解决了。 Android 内部使用了一项服务,可以管理 USB 设备和配件。 此服务对第三方开发人员是隐藏的,并且没有记录在案。如果您检查 UsbPermissionActivity 的源代码,您将能够弄清楚该服务是如何被调用的。 为了调用服务 IUsbManager 接口和 ServiceManager 类被使用。这些都是隐藏的,所以你不能直接使用它们。但你能做的是 在相应的命名空间(包)中创建具有完全相同名称的存根。然后您就可以编译该代码,而运行时环境将使用真实的东西。

唯一的要求您的应用程序必须是系统应用程序 - 即它必须位于 /system/app/ 目录中。由于您的设备已植根,这应该不是问题。

因此,您必须在项目中添加一个包:“android.hardware.usb”并在其中放入一个名为“IUsbManager.java”的文件,其中包含以下内容:

package android.hardware.usb;

public interface IUsbManager extends android.os.IInterface

    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements android.hardware.usb.IUsbManager
    
        /** Construct the stub at attach it to the interface. */
        public Stub()
        
            throw new RuntimeException( "Stub!" );
        
        /**
         * Cast an IBinder object into an android.hardware.usb.IUsbManager interface,
         * generating a proxy if needed.
         */
        public static android.hardware.usb.IUsbManager asInterface( android.os.IBinder obj )
        
            throw new RuntimeException( "Stub!" );
        

        public android.os.IBinder asBinder()
        
            throw new RuntimeException( "Stub!" );
        

        public boolean onTransact( int code, android.os.Parcel data, android.os.Parcel reply, int flags ) throws android.os.RemoteException
        
            throw new RuntimeException( "Stub!" );
        

        static final int TRANSACTION_getDeviceList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_openDevice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_getCurrentAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_openAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
        static final int TRANSACTION_setDevicePackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
        static final int TRANSACTION_setAccessoryPackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
        static final int TRANSACTION_hasDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
        static final int TRANSACTION_hasAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
        static final int TRANSACTION_requestDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
        static final int TRANSACTION_requestAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
        static final int TRANSACTION_grantDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
        static final int TRANSACTION_grantAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
        static final int TRANSACTION_hasDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);
        static final int TRANSACTION_clearDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);
        static final int TRANSACTION_setCurrentFunction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);
        static final int TRANSACTION_setMassStorageBackingFile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);
    

    /* Returns a list of all currently attached USB devices */
    public void getDeviceList( android.os.Bundle devices ) throws android.os.RemoteException;
    /* Returns a file descriptor for communicating with the USB device.
         * The native fd can be passed to usb_device_new() in libusbhost.
         */
    public android.os.ParcelFileDescriptor openDevice( java.lang.String deviceName ) throws android.os.RemoteException;
    /* Returns the currently attached USB accessory */
    public android.hardware.usb.UsbAccessory getCurrentAccessory() throws android.os.RemoteException;
    /* Returns a file descriptor for communicating with the USB accessory.
         * This file descriptor can be used with standard Java file operations.
         */
    public android.os.ParcelFileDescriptor openAccessory( android.hardware.usb.UsbAccessory accessory ) throws android.os.RemoteException;
    /* Sets the default package for a USB device
         * (or clears it if the package name is null)
         */
    public void setDevicePackage( android.hardware.usb.UsbDevice device, java.lang.String packageName ) throws android.os.RemoteException;
    /* Sets the default package for a USB accessory
         * (or clears it if the package name is null)
         */
    public void setAccessoryPackage( android.hardware.usb.UsbAccessory accessory, java.lang.String packageName ) throws android.os.RemoteException;
    /* Returns true if the caller has permission to access the device. */
    public boolean hasDevicePermission(android.hardware.usb.UsbDevice device) throws android.os.RemoteException;
    /* Returns true if the caller has permission to access the accessory. */
    public boolean hasAccessoryPermission( android.hardware.usb.UsbAccessory accessory ) throws android.os.RemoteException;
    /* Requests permission for the given package to access the device.
         * Will display a system dialog to query the user if permission
         * had not already been given.
         */
    public void requestDevicePermission( android.hardware.usb.UsbDevice device, java.lang.String packageName, android.app.PendingIntent pi ) throws android.os.RemoteException;
    /* Requests permission for the given package to access the accessory.
         * Will display a system dialog to query the user if permission
         * had not already been given. Result is returned via pi.
         */
    public void requestAccessoryPermission( android.hardware.usb.UsbAccessory accessory, java.lang.String packageName, android.app.PendingIntent pi ) throws android.os.RemoteException;
    /* Grants permission for the given UID to access the device */
    public void grantDevicePermission( android.hardware.usb.UsbDevice device, int uid ) throws android.os.RemoteException;
    /* Grants permission for the given UID to access the accessory */
    public void grantAccessoryPermission( android.hardware.usb.UsbAccessory accessory, int uid ) throws android.os.RemoteException;
    /* Returns true if the USB manager has default preferences or permissions for the package */
    public boolean hasDefaults( java.lang.String packageName ) throws android.os.RemoteException;
    /* Clears default preferences and permissions for the package */
    public void clearDefaults( java.lang.String packageName ) throws android.os.RemoteException;
    /* Sets the current USB function. */
    public void setCurrentFunction( java.lang.String function, boolean makeDefault ) throws android.os.RemoteException;
    /* Sets the file path for USB mass storage backing file. */
    public void setMassStorageBackingFile( java.lang.String path ) throws android.os.RemoteException;

然后是另一个包:“android.os”和“ServiceManager.java”:

package android.os;

import java.util.Map;

public final class ServiceManager

    public static IBinder getService( String name )
    
        throw new RuntimeException( "Stub!" );
    

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService( String name, IBinder service )
    
        throw new RuntimeException( "Stub!" );
    

    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    public static IBinder checkService( String name )
    
        throw new RuntimeException( "Stub!" );
    

    public static String[] listServices() throws RemoteException
    
        throw new RuntimeException( "Stub!" );
    

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     * 
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache( Map<String, IBinder> cache )
    
        throw new RuntimeException( "Stub!" );
    

请注意,这些类的接口可能会根据 Android 的版本而有所不同。就我而言,版本是 4.0.3。 因此,如果您有其他版本的 Android 并且此代码不起作用,您将不得不检查您的特定操作系统版本的源代码。

以下是使用该服务向所有 FTDI 设备授予权限的示例:

import java.util.HashMap;
import java.util.Iterator;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.IBinder;
import android.os.ServiceManager;

public class LaunchReceiver extends BroadcastReceiver

    public void onReceive( Context context, Intent intent )
    
        String action = intent.getAction();
        if( action != null && action.equals( Intent.ACTION_BOOT_COMPLETED ) )
        
            try
            
                PackageManager pm = context.getPackageManager();
                ApplicationInfo ai = pm.getApplicationInfo( YOUR_APP_PACKAGE_NAMESPACE, 0 );
                if( ai != null )
                
                    UsbManager manager = (UsbManager) context.getSystemService( Context.USB_SERVICE );
                    IBinder b = ServiceManager.getService( Context.USB_SERVICE );
                    IUsbManager service = IUsbManager.Stub.asInterface( b );

                    HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
                    Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
                    while( deviceIterator.hasNext() )
                    
                            UsbDevice device = deviceIterator.next();
                            if( device.getVendorId() == 0x0403 )
                            
                                service.grantDevicePermission( device, ai.uid );
                                service.setDevicePackage( device, YOUR_APP_PACKAGE_NAMESPACE );
                            
                    
                
            
            catch( Exception e )
            
                trace( e.toString() );
            
        
    

还有一件事 - 您必须在清单中添加以下权限(Lint 可能不喜欢它,但您始终可以在项目属性中更改严重级别):

<uses-permission android:name="android.permission.MANAGE_USB" />

【讨论】:

谢谢,我会检查并通知您。 在 4.2.2 上它不起作用,因为 setDevicePackage() 已更改。检查我的代码答案。 如何将它用于 USB 配件? 它在启动时工作。但是如果我重新插入 FTDI 设备,对话框仍然会显示(尽管我单击“取消”,它仍然有效)。我正在使用 FDTI 的 d2xx 库。图书馆在某个地方叫mUsbManager.requestPermission(device, mPermissionIntent);吗?那我就无所谓了。 哦,this intent-filter method。如果我在清单上声明一个不可见的活动(不知道为什么接收器和服务不起作用),它就可以工作。重新插入设备,对话框将不会显示。【参考方案10】:

根据 Android Developers 上的文档,当您的应用通过您的清单意图过滤器启动时,您已经拥有连接 USB 设备的权限。也许您应该尝试这种方法并编写一个过滤器以与您要使用的设备完全匹配,以防止其他应用也想与该设备进行通信。

见http://developer.android.com/guide/topics/connectivity/usb/host.html#permission-d上的“备注”

【讨论】:

它不起作用,我已将所有这些意图过滤器添加到我的活动中,但它仍然没有权限 它仅用于过滤设备(按供应商、产品 ID)。它与设备权限无关! @user924 "注意:如果您的应用程序使用意图过滤器在连接 USB 设备时发现它们,如果用户允许您的应用程序处理意图,它会自动获得权限。如果没有,您必须在连接到设备之前,在您的应用程序中明确请求权限。” 在所有情况下都会弹出一个带有请求权限的对话框,自己试试吧(我有所有的意图过滤器、设备/供应商 ID,我的接收器检测到设备已连接或断开连接但仍需要权限) .无论如何,我找到了一种使用 Root 和系统应用程序来避免它的方法 并且该解决方案在重新启动后不起作用。所以是的,您可以插入/拔出设备,它会自动授予权限,但是一旦您重新启动设备,您需要再次手动请求或拔出/拔出设备。没用!【参考方案11】:

实现这一点的一种方法,请注意,这实际上并没有消除确认,而是精确定位 checkbox 的位置并使用 Android 等效的 Robot 类选择它,然后选择OK。您可以编写一个在后台运行的应用程序,它甚至可以被您提到的启动服务调用,专门用于此目的。

【讨论】:

我做了同样的事情,但是后台服务一直无法访问对话框,并且出现错误。 这很愚蠢,我想控制一个没有活动但通过服务的设备【参考方案12】:

我认为我们可以通过对/etc/udev 进行一些修改来做到这一点。我们可以将供应商 ID 和设备 ID 添加到 51-android.rules 文件中。

【讨论】:

这与它无关。关键是不能连接到他/她已经能够做到的设备,它是为了防止出现对话框确认。 Android 没有这样的文件/etc/udev。这不是 Ubuntu! 这个文件用于检测 Ubuntu 上的设备。你在这里发布了一个完全随机的东西【参考方案13】:

Android 并不是专门为支持这种开箱即用的用法而设计的。就个人而言,对于非交互式使用,我很想考虑在 linux 内核中使用 USB 串行驱动程序并跳过 android USB api。但是您必须能够认真修改 android 安装 - 更改内核配置和/或加载模块,创建设备文件并设置其权限或所有者,可能为允许的应用添加 unix 组和 android 权限访问它。

或者您可以查看android源并禁用用户确认;但是如果您没有为设备提供源代码 android 构建,这可能比 linux 级别的想法更棘手,因为将开源 android 调整为在供应商设备上运行可能并非易事(除非有人已经提供了来自- 对相关设备具有足够功能的源构建)

顺便说一句,root/su 访问权限不适用于应用程序本身 - 它仅意味着知道如何运行您的 root hack 留下的任何工具的应用程序可以启动以 root 身份运行的帮助程序,但应用程序本身没有也不能。使用 root 在系统分区上安装应用程序可能会获得一些非典型的 android 权限,但您必须检查是否有任何可以帮助您使用 USB 的权限。

【讨论】:

只是一个理论答案

以上是关于绕过android usb主机权限确认对话框的主要内容,如果未能解决你的问题,请参考以下文章

在 Android Kiosk 应用程序上显示 USB 权限对话框?

Android USB 开发:如何跳过USB权限询问

Android 5.0 Usb调试拦截分析及修改

如何为 libusb android 应用程序授予 /dev/bus/usb 权限?

Android 连接USB设备(主机模式)

android默认开启adb调试方法分析