java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.SCAN_RESULTS flg

本文针对Android应用中出现的广播接收异常问题进行分析,探讨了由于广播接收器与Activity不匹配导致的错误,并提出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


E/AndroidRuntime: FATAL EXCEPTION: main

                  Process: com.nokia.wlanapp, PID: 18526
                  java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.SCAN_RESULTS flg=0x4000010 (has extras【外部】) } in com.nokia.wlanapp.Receiver.WifiReceiver@22f1b23
                      at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:975)
                      at android.os.Handler.handleCallback(Handler.java:815)
                      at android.os.Handler.dispatchMessage(Handler.java:104)
                      at android.os.Looper.loop(Looper.java:207)
                      at android.app.ActivityThread.main(ActivityThread.java:5902)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806)
                   Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
                      at android.app.Activity.getSystemService(Activity.java:5383)
                      at android.widget.SimpleAdapter.<init>(SimpleAdapter.java:93)
                      at com.nokia.wlanapp.view.impl.WlanListActivity.setWlanApList(WlanListActivity.java:50)
                      at com.nokia.wlanapp.presenter.WlanListPresenter.getWlanApList(WlanListPresenter.java:45)
                      at com.nokia.wlanapp.Receiver.WifiReceiver.onReceive(WifiReceiver.java:21)
                      at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:963)
                      at android.os.Handler.handleCallback(Handler.java:815) 
                      at android.os.Handler.dispatchMessage(Handler.java:104) 
                      at android.os.Looper.loop(Looper.java:207) 
                      at android.app.ActivityThread.main(ActivityThread.java:5902) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806) 
I/Process: Sending signal. PID: 18526 SIG: 9

Disconnected from the target VM, address: 'localhost:8604', transport: 'socket'


问题在代码new的问题。


WifiReceiver.java




WlanListActivity.java



WlanListPresenter.java



问题是:

广播new出来的WlanListPresenter对象,activity页面new出来的WlanListPresenter对象不是同一个,
WlanListPresenter构造方法构造的页面不是new了WlanListPresenter对象的Activity页面。
所以报 has extras,它们是外部的,没有各自的联系。

解决方法:
广播作为页面Activity的内部类
WlanListPresenter构造方法传入new WlanListPresenter的Activity




<think>我们正在处理一个Android运行时异常:Error receiving broadcast Intent USB_ACCESSORY_DETACHED。这个异常通常发生在注册了广播接收器(BroadcastReceiver)来监听USB附件分离事件(`UsbManager.ACTION_USB_ACCESSORY_DETACHED`)时,但在广播传递时接收器已经注销或未正确注册,或者在处理广播时发生了异常。 ### 问题分析 1. **异常原因**:当USB附件被拔出时,系统会发送一个`ACTION_USB_ACCESSORY_DETACHED`的广播。如果应用注册了一个广播接收器来监听这个事件,但在广播到达时,接收器已经被注销(例如,Activity已经销毁但未及时注销接收器),或者接收器在处理广播时抛出了异常(如空指针等),就会导致这个错误。 2. **常见场景**: - 在Activity中动态注册了广播接收器,但在Activity销毁(如旋转屏幕、按返回键)时没有及时注销。 - 在广播接收器的`onReceive`方法中执行了耗时操作或访问了已经不存在的资源(如已经销毁的Activity的视图)。 ### 解决方案 1. **确保及时注销广播接收器**: 在Activity或Fragment的生命周期中,动态注册的广播接收器必须在相应的时机注销。通常,在`onResume`中注册,在`onPause`中注销;或者`onStart`中注册,`onStop`中注销。注意保持注册和注销的对称。 示例代码: ```java public class MyActivity extends Activity { private BroadcastReceiver mUsbReceiver; @Override protected void onResume() { super.onResume(); mUsbReceiver = new UsbAccessoryDetachedReceiver(); IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED); registerReceiver(mUsbReceiver, filter); } @Override protected void onPause() { super.onPause(); if (mUsbReceiver != null) { unregisterReceiver(mUsbReceiver); mUsbReceiver = null; } } } ``` 2. **避免在广播接收器中执行耗时操作**: 广播接收器的`onReceive`方法运行在主线程中,并且必须快速执行(Android系统要求在几秒内完成)。如果需要进行耗时操作,应该启动一个Service来处理,而不是在接收器中直接处理。 3. **处理广播接收器中的异常**: 在`onReceive`方法内部,应该捕获所有可能的异常,避免崩溃。 ```java private class UsbAccessoryDetachedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { // 处理广播 } catch (Exception e) { // 记录异常或进行其他处理 } } } ``` 4. **使用应用上下文注册**: 如果广播接收器不需要与Activity的界面交互,可以考虑使用Application Context注册,并注意在合适的时机(如应用退出时)注销。但通常还是建议在Activity中注册,以便与生命周期关联。 5. **检查USB权限**: 在处理USB附件时,确保已经获取了必要的权限。当附件被拔出时,可能涉及到一些需要权限的操作,如果没有权限可能会导致异常。 ### 其他建议 - 使用日志记录:在广播接收器中添加日志,以便跟踪广播的接收和处理过程。 - 使用Android Studio的调试工具:在广播接收器中设置断点,观察广播到达时接收器是否还存在,以及处理过程中是否有异常。 ### 总结 该异常通常是由于广播接收器在广播到达时已经不存在,或者在处理广播时抛出了未捕获的异常。通过确保及时注销接收器、避免耗时操作、捕获异常等方法可以解决此问题。 §§相关问题§§ 1. Android中动态注册广播接收器的最佳实践是什么? 2. 如何处理广播接收器中的耗时操作? 3. 为什么在Activity销毁时要注销广播接收器? 4. 除了USB附件分离事件,还有哪些常见的广播事件需要特别注意生命周期管理?</think>### Android RuntimeException: Error receiving broadcast Intent USB_ACCESSORY_DETACHED 这个错误通常发生在以下场景:您的应用注册了广播接收器(`BroadcastReceiver`)监听USB附件分离事件(`UsbManager.ACTION_USB_ACCESSORY_DETACHED`),但当USB设备被拔出时,广播接收器无法正确处理该事件。以下是原因分析和解决方案: #### 常见原因 1. **接收器未注销** 当Activity/Fragment销毁时未注销广播接收器,系统仍会向其发送广播,但此时接收器已失效。 2. **空指针异常** 在`onReceive()`中访问了已销毁的UI组件或空对象。 3. **多线程冲突** 在接收器中执行耗时操作导致主线程阻塞,同时Activity被销毁。 4. **权限问题** 缺少USB操作权限或未在清单中正确声明接收器。 #### 解决方案 ##### 1. 确保正确注销广播接收器 在Activity/Fragment生命周期结束时注销接收器: ```java // 在Activity中 private BroadcastReceiver usbReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 处理USB事件 } }; @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED); registerReceiver(usbReceiver, filter); // 注册 } @Override protected void onPause() { super.onPause(); unregisterReceiver(usbReceiver); // 注销 } ``` ##### 2. 添加空值检查 在`onReceive()`中访问UI前检查Activity状态: ```java public void onReceive(Context context, Intent intent) { if (getActivity() == null || getActivity().isFinishing()) return; // 检查Activity状态 // 安全操作UI组件 TextView statusView = getActivity().findViewById(R.id.tv_status); if (statusView != null) { statusView.setText("USB设备已拔出"); } } ``` ##### 3. 避免耗时操作 将耗时操作移至后台线程: ```java public void onReceive(Context context, Intent intent) { new Thread(() -> { // 后台执行耗时操作 processUsbDisconnect(intent); }).start(); } ``` ##### 4. 检查权限配置 在`AndroidManifest.xml`中声明接收器: ```xml <receiver android:name=".UsbDisconnectReceiver"> <intent-filter> <action android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" /> </intent-filter> </receiver> ``` ##### 5. 使用应用上下文 对于全局事件监听,使用`ApplicationContext`注册接收器: ```java context.getApplicationContext().registerReceiver(receiver, filter); ``` #### 调试建议 1. **日志追踪** 在`onReceive()`首尾添加日志定位崩溃点: ```java Log.d("USBReceiver", "广播到达"); // ...代码逻辑... Log.d("USBReceiver", "广播处理完成"); ``` 2. **异常捕获** 包裹整个`onReceive()`逻辑: ```java try { // 处理逻辑 } catch (Exception e) { Log.e("USBReceiver", "处理异常: " + e.getMessage()); } ``` 3. **USB权限验证** 检查是否已获取USB设备权限: ```java UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE); if (!manager.hasPermission(usbAccessory)) { // 请求权限 } ``` > **关键点**:该错误的本质是**组件生命周期与广播投递的时序冲突**。通过严格匹配注册/注销时机、添加健壮性检查、异步处理耗时任务,可彻底解决此问题[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松门一枝花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值