绕过android usb主机权限确认对话框
我想在工业中使用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
没有人点击确定。
即使当我检查默认使用…checkbox,如果我重新插入USB,或重新启动主机设备,它会在下次启动时再次提问。
我用超级用户模式运行了服务和应用程序,但没有区别,它再次询问。
我添加了意图filter,但没有区别,它每次都问我。
<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" />
任何意见如何绕过或禁用它?
我有根和SU访问。
我知道这有点晚了,但仍然…
我有同样的问题,我想我已经设法解决这个问题。 Android内部使用的服务可以pipe理USB设备和配件。 这项服务是从第三方开发者隐藏的,没有logging。 如果您检查UsbPermissionActivity的源代码,您将能够找出如何调用该服务。 为了调用服务,使用IUsbManager接口和ServiceManager类。 这些都是隐藏的,所以你不能直接使用它们。 但是你可以做的是用完全相同的名字和相应的命名空间(包)来创build他们的存根。 那么你就可以编译这个代码,而运行时环境将使用真实的东西。
唯一的要求是你的应用程序必须是一个系统 – 它必须位于/ 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() ); } } } }
还有一件事 – 你必须添加下列权限到你的清单(林特可能不喜欢它,但你总是可以改变项目属性的严重性级别):
<uses-permission android:name="android.permission.MANAGE_USB" />
@d_d_t aswer是伟大的,但它不适用于新的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 ); ....
如果你有select编译Android系统,那么你不能做任何事情。
你可以加
public void onStart() { super.onStart(); mPermissionGranted = true; finish(); }
到frameworks / base / packages / SystemUI / src / com / android / systemui / usb / UsbPermissionActivity.java
绕过权限确认popup窗口。
Android实际上不是为了支持这种使用方式而devise的。 就个人而言,对于非交互式的使用,我很想考虑在Linux内核中使用USB串行驱动程序,并跳过android USB apis。 但是你必须能够认真地修改android安装 – 更改内核configuration和/或加载模块,创build设备文件并设置他们的权限或所有者,可能添加一个unix组和android权限允许应用程序访问它。
或者你可以通过android源代码来查看并禁用用户确认; 但是如果你没有从设备的源代码构buildAndroid,这可能比linux级别的想法更棘手,因为适应开放源代码的android在供应商设备上运行可能是不平凡的(除非有人已经提供了from对于所讨论的设备而言足够function的源构build)
根本上,root / su访问权限并不适用于应用程序本身 – 它只意味着知道如何运行root root攻击所留下的任何工具的应用程序可以启动一个以root身份运行的帮助程序,但是应用程序本身不会不能。 使用root在系统分区上安装应用程序可能会给你一些非典型的android权限,但你必须检查是否有任何帮助你的USB。
根据Android开发人员的文档,当您的应用程序开始通过您的清单意图filter时,您已经拥有连接的USB设备的权限。 也许你应该尝试这种方法,并写一个filter来精确匹配你想使用的设备,以防止其他应用程序也希望与设备进行通信。
请参阅http://developer.android.com/guide/topics/connectivity/usb/host.html#permission-d上的“注意事项”;
我有popup窗口相同的问题,没有人点击它。 但我发现了一个不同的解决scheme(对于根植设备)。 popup窗口是由UsbPermissionActivity类中的android生成的(UsbPermissionActivity由UsbSettingsManager启动)。 看看Android的源代码,看看发生了什么。 这里的好处是,我们可以操纵UsbPermissionActivity的字节码来接受所有的UsbDevices。 你需要Smali / Baksmali这个工具。 https://code.google.com/p/smali/
- 在您的设备上find文件SystemUI.apk
- 使用
adb pull path/to/SystemUI.apk
将其复制到您的计算机 - 解压apk
- 使用
java -jar baksmali.jar classes.dex
反汇编classes.dex文件 -
find文件UsbPermissionActivity,并find它所在的行
invoke-virtual {p0}, Lcom/android/systemui/usb/UsbPermissionActivity;->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.dexreplace为SystemUI.apk
- 用
adb push services.jar path/to/SystemUI.apk
replace设备上的原始SystemUI.apk,或者如果这不适用于filemanager ap
一种方法来实现这一点,请注意,这实际上并没有摆脱确认,将是确定checkbox
的位置,并使用机器人类的Android等效select它,然后selectOK
。 您可以编写一个在后台运行的应用程序,甚至可以由您提到的启动服务来调用,专门用于此目的。
我认为预先列出您使用的附件是最好的解决scheme。 为此,您需要在此位置/ data / system / users / 0处添加文件usb_device_manager.xml
//注意0是用户ID,如果你没有在Android中添加更多的用户,它可能会是0,但是如果你确实改变了这个ID
这是文件应该看起来如何:
<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>
如果你只是想复制/写入一个USB棒,你可以使用
下面的方法用linx命令doCommand(“mkdir / mnt / usbhost1 / dirname”)
private boolean doCommand(String[] commands) { boolean ran = false; try { Process process = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); for (String single : commands) { os.writeBytes(single + "\n"); os.flush(); } os.writeBytes("exit\n"); os.flush(); process.waitFor(); ran = true; } catch(Exception ex) { } return ran; }
我在清单中拥有以下权限,抱歉不记得哪些是必须的。
<permission android:name="com.android.example.USB_PERMISSION"/> <permission android:name= "android.permission.INSTALL_PACKAGES"/> <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <data android:scheme="file" />
如果你想做其他事情,对你来说可能不是很有用
我想我们可以通过在/etc/udev
进行一些修改来做到这一点。 我们可以将供应商ID和设备ID添加到51-android.rules
文件中。
在第一次需要确认的时候,你可以select“always”,然后即使Android设备断电,并且通电,你的应用程序仍然有访问USB2Serial的权限。 只是说,只有一次确认!