绕过android USB主机权限确认对话框 [英] bypass android usb host permission confirmation dialog

查看:40
本文介绍了绕过android USB主机权限确认对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在工业上使用android,

I want to use android in industry,

我可以毫无问题地连接到带有 slickdevlabs.com 库的 Profilic 和 Ftdi USB 转串口芯片.

I can connect to Profilic and Ftdi USB to Serial chips with slickdevlabs.com library without any problem.

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

The application has a service and it starts on boot,connect to the usb serial port and do the other things.

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

my problem is that the host device does not have any interaction with user,

所以当机器人问

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

没有人点击确定.

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

even when I check the use by default... checkbox,If I reinsert the USB ,or reboot the host device, it asks again on next boot.

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

I ran the service and app with SuperUser mode,but no difference,it asks again.

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

I added intent filter but no difference,it asks me every time.

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

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

Any opinion how to bypass or disable it ?

我有 root 和 SU 访问权限.

I have root and SU access.

推荐答案

我知道有点晚了,但仍然......

I know it's a bit late, but still...

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

I had the same kind of problem and I think I've managed to solve it. There's a service that Android uses internally that allows to manage USB devices and accessories. This service is hidden from thrid party developers and is not documented. If you check the source code for UsbPermissionActivity you'll be able to figure out how that service is called. In order to call the service IUsbManager interface and ServiceManager class are employed. These are both hidden too, so you can't use them directly. But what you can do is to create their stubs with exactly the same names and in corresponding namespaces (packages). Then you'll be able to compile that code, while the runtime environment will use the real things.

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

The only requirement is that your application has to be a system one - that is it has to be located in /system/app/ directory. Since your device is rooted that shouldn't be a problem.

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

So you will have to add a package to your project: "android.hardware.usb" and put a file in it named "IUsbManager.java" with the following content:

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":

Then another package: "android.os" with "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 并且此代码不起作用,则必须检查您的特定操作系统版本的源代码.

Note that interfaces of these classes may change depending on the version of Android. In my case the version is 4.0.3. So if you have another version of Android and this code doesn't work you will have to check the source code for your particular version of OS.

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

Here's an example of using the service to grant permissions to all FTDI devices:

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 可能不喜欢它,但您可以随时更改项目属性中的严重性级别):

One more thing - you will have to add the following permission to your manifest (Lint might not like it but you can always change severity level in your project's properties):

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

这篇关于绕过android USB主机权限确认对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆