Android监听USB插拔事件

本文介绍了在Android中如何监听USB设备的插拔事件,包括通过Mainfest.xml注册和在代码中遍历匹配的方法。重点提及了android.hardware.usb.action.USB_DEVICE_ATTACHED意图以及device_filter.xml配置文件的作用。

Android监听USB插拔事件有两种方式:

一种是在Mainifest.xml中注册

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

android.hardware.usb.action.USB_DEVICE_ATTACHED即在usb插入是的action意图。在android.hardware.usb.UsbManager类中有多种action的定义,有兴趣的可以查看一下。

device_filter.xml文件是对usb端口和接口的过滤。

<

<think>我们正在处理一个关于Android开发的问题:用户需要获取一个全局监听USB插拔事件的广播接收器示例代码。根据Android开发知识,我们知道USB插拔事件是通过系统广播发送的,因此我们可以通过注册广播接收器来监听这些事件。具体来说,我们需要监听两个系统广播:-`android.hardware.usb.action.USB_DEVICE_ATTACHED`(USB设备连接)-`android.hardware.usb.action.USB_DEVICE_DETACHED`(USB设备断开)注意:由于这些广播是系统级别的,我们需要在AndroidManifest.xml中静态注册广播接收器,并且需要声明相应的权限(如果需要的话)。但是,从Android8.0(API26)开始,对静态注册广播接收器有了限制,很多系统广播不再允许静态注册。因此,对于USB插拔事件,我们通常采用动态注册的方式。但是,用户要求的是“全局监听”,这意味着即使应用没有运行,也要能接收到广播。然而,从Android8.0开始,大多数隐式广播(包括USB插拔广播)不允许静态注册,除了少数豁免的广播。我们需要确认USB插拔广播是否在豁免列表中。查阅Android官方文档:USB主机概览(https://developer.android.com/guide/topics/connectivity/usb/host)中提到,可以通过两种方式检测USB设备:一种是静态广播接收器,另一种是动态广播接收器。但是,静态广播接收器只能用于在设备连接时启动应用(如果应用尚未运行)。而且,静态注册需要指定一个Activity来处理用户连接设备的请求(通过intent-filter)。不过,对于纯粹的监听插拔事件,官方文档更倾向于使用动态注册。但是,用户要求的是全局监听,即无论应用是否运行都能接收到。因此,我们需要考虑以下方案:1.对于Android8.0以下,我们可以使用静态注册。2.对于Android8.0及以上,由于限制,静态注册可能无效,但我们可以考虑使用动态注册,但动态注册要求应用进程在运行。因此,要实现真正的全局监听(即使应用被杀掉也能监听到),可能需要结合其他方法,比如使用一个前台服务来保持进程运行并动态注册广播。然而,实际上,根据官方文档,USB设备连接广播(`USB_DEVICE_ATTACHED`)是允许静态注册的例外广播之一(在Android8.0及以上)。因此,我们可以静态注册这个广播。但是,断开广播(`USB_DEVICE_DETACHED`)并不在豁免列表中,因此不能静态注册。因此,我们需要:-静态注册`USB_DEVICE_ATTACHED`广播,这样当设备连接时,即使应用没有运行,系统也会启动我们的应用(或者至少启动广播接收器)。-动态注册`USB_DEVICE_DETACHED`广播,因为无法静态注册。这意味着我们需要在应用启动后(比如在Activity或Service中)动态注册断开广播。但是,用户可能希望同时监听连接和断开事件,并且要求全局监听。那么,我们可以这样处理:-静态注册连接事件:当连接事件发生时,系统会启动我们的广播接收器(或者启动我们的应用),然后我们在广播接收器中启动一个服务,并在服务中动态注册断开事件。这样,当设备断开时,我们就能在服务中收到断开事件。另外,我们还需要注意,静态注册`USB_DEVICE_ATTACHED`广播时,需要在intent-filter中指定设备信息(如vendor-id和product-id),以便系统知道我们关心哪种设备。如果我们想监听所有USB设备,我们也可以不指定,但是这样可能会接收到所有USB设备的连接事件,但这样可能会被系统限制(因为安全原因)。考虑到用户可能希望监听所有USB设备的插拔,我们可以这样:步骤:1.在AndroidManifest.xml中静态注册一个广播接收器,用于接收`USB_DEVICE_ATTACHED`广播。2.在广播接收器的onReceive方法中,启动一个服务(比如IntentService或JobIntentService),在这个服务中动态注册`USB_DEVICE_DETACHED`广播。3.同时,在服务中,我们也可以处理连接事件。4.为了确保服务能够持续运行以接收断开事件,我们可以将服务设置为前台服务(避免被系统杀死)。但是,这种方法可能会因为长时间运行服务而消耗电量,用户可能不希望这样。另一种思路:既然连接事件可以静态注册,那么当连接事件发生时,应用被唤醒,然后我们动态注册断开事件,并在处理完断开事件后(即设备断开后)停止服务。这样,服务只会在设备连接后运行,直到设备断开。下面,我们给出一个示例代码:首先,在AndroidManifest.xml中静态注册连接事件的广播接收器:```xml<receiver android:name=".UsbAttachedReceiver"><intent-filter><action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/></intent-filter> </receiver> ```然后,创建广播接收器`UsbAttachedReceiver`,用于接收连接事件,并启动服务: ```javapublic classUsbAttachedReceiver extendsBroadcastReceiver{@Overridepublic voidonReceive(Context context, Intentintent){if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {//启动服务,在服务中动态注册断开事件Intent serviceIntent =new Intent(context,UsbMonitorService.class);serviceIntent.putExtra("action","attached");context.startService(serviceIntent);//注意:如果使用Android8.0及以上,需要改为startForegroundService//context.startForegroundService(serviceIntent);}}} ```接下来,创建服务`UsbMonitorService`,在服务中动态注册断开事件的广播接收器:```javapublicclass UsbMonitorService extendsService {privateUsbDetachedReceiver mUsbDetachedReceiver;@OverridepublicvoidonCreate(){super.onCreate();//动态注册断开事件的广播接收器mUsbDetachedReceiver =new UsbDetachedReceiver();IntentFilterfilter =new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);registerReceiver(mUsbDetachedReceiver, filter);}@Overridepublic intonStartCommand(Intent intent, intflags,int startId){//如果从连接事件启动,这里可以处理连接事件String action= intent.getStringExtra("action");if ("attached".equals(action)){//处理USB设备连接//获取USB设备信息UsbDevice device= intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if(device!= null) {//处理设备连接}}//为了成为前台服务,避免被系统杀死(如果设备连接后需要长时间运行直到断开)//设置前台服务startForeground(1,createNotification());return START_STICKY;}privateNotification createNotification(){//创建通知,用于前台服务//需要创建通知渠道(针对Android8.0及以上)//这里省略具体创建通知的代码return newNotification();}@Overridepublicvoid onDestroy(){super.onDestroy();//取消注册广播接收器unregisterReceiver(mUsbDetachedReceiver);}@OverridepublicIBinderonBind(Intentintent){return null;} }```然后,在服务中动态注册的断开事件广播接收器`UsbDetachedReceiver`(作为内部类):```javapublicclass UsbDetachedReceiverextends BroadcastReceiver {@Overridepublicvoid onReceive(Contextcontext,Intent intent) {if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {//获取断开的设备UsbDevice device= intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if(device!= null) {//处理设备断开}//设备断开后,停止服务context.stopService(newIntent(context, UsbMonitorService.class));}} }```注意:以上代码只是一个示例,实际应用中需要处理更多细节,比如权限请求(因为访问USB设备可能需要权限),以及不同Android版本的适配(如使用startForegroundService等)。另外,对于Android8.0及以上,静态注册`USB_DEVICE_ATTACHED`广播时,还需要注意,如果应用的目标SDK版本>=26,则必须在AndroidManifest.xml中显式声明广播接收器的`exported`属性(通常设为true,因为要接收系统广播)以及权限。此外,如果用户希望监听所有USB设备,那么静态注册时不需要指定设备信息。但是,如果只想监听特定设备,则可以在intent-filter中指定`<meta-data>`。由于用户要求的是全局监听USB插拔,我们提供了上述方案。但请注意,从Android10(API29)开始,后台启动服务的限制更加严格,因此可能需要使用JobScheduler代替服务。但考虑到我们需要动态注册广播接收器,使用服务可能是必要的,而前台服务可以避免后台限制。最后,我们还需要在AndroidManifest.xml中声明服务:```xml<service android:name=".UsbMonitorService"/>```并且,为了使用前台服务,我们需要在AndroidManifest.xml中添加权限:```xml<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> ```以上代码示例为用户提供了一个基本的框架。用户可能需要根据实际需求进行调整。注意:由于Android版本差异和不同设备的兼容性问题,实际效果可能有所不同。生成相关问题:1.如何适配Android8.0以上的广播限制?2.如何请求USB设备的访问权限?3.如何处理多个USB设备的插拔事件?</think>### Android全局监听USB插拔广播接收器示例 在Android系统中,可以通过广播接收器全局监听USB设备的插拔事件。以下是完整的实现方案: #### 1. 广播接收器实现 ```java public class UsbBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "UsbBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { Log.d(TAG, "USB设备已连接: " + (device != null ? device.getDeviceName() : "未知")); // 处理连接逻辑 } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { Log.d(TAG, "USB设备已断开: " + (device != null ? device.getDeviceName() : "未知")); // 处理断开逻辑 } } } ``` #### 2. AndroidManifest.xml静态注册 ```xml <application> <receiver android:name=".UsbBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /> </intent-filter> </receiver> </application> ``` #### 3. 动态注册(可选,用于运行时监听) ```java public class MainActivity extends AppCompatActivity { private UsbBroadcastReceiver usbReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); usbReceiver = new UsbBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); registerReceiver(usbReceiver, filter); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(usbReceiver); // 避免内存泄漏 } } ``` #### 关键说明: 1. **广播类型**: - `ACTION_USB_DEVICE_ATTACHED`:USB设备连接 - `ACTION_USB_DEVICE_DETACHED`:USB设备断开 - 通过`UsbManager.EXTRA_DEVICE`获取设备对象 2. **适配性注意**: - Android 8.0+系统对静态广播接收器有限制,但USB广播属于[豁免列表](https://developer.android.com/guide/components/broadcast-exceptions),静态注册仍有效[^1] - 动态注册需在Activity/Fragment生命周期内管理,适合临时监听 3. **设备信息获取**: ```java if (device != null) { int vendorId = device.getVendorId(); int productId = device.getProductId(); String deviceName = device.getDeviceName(); } ``` 4. **权限处理**: - 需要声明USB权限(非必须): ```xml <uses-feature android:name="android.hardware.usb.host" /> ``` #### 常见问题解决: - **无法接收广播**:检查广播名称拼写,确认设备支持USB主机模式 - **重复接收**:使用单例模式管理接收器,或添加`android:permission`限制 - **Android 10+适配**:在`AndroidManifest.xml`中添加: ```xml <queries> <intent> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent> </queries> ``` > **提示**:对于需要深度控制USB设备的场景,还需结合`UsbManager`和`UsbDeviceConnection`类进行通信[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值