
在开发需要与usb设备交互的android应用时,我们通常会利用android.hardware.usb.action.usb_device_attached这一intent动作来监听设备的连接事件。当usb设备插入时,系统会广播此intent,如果我们的应用在androidmanifest.xml中配置了相应的intent-filter,便能响应这一事件。
然而,一个常见的问题是,当应用已经在前台运行时,如果用户断开并重新连接USB设备,应用可能会意外重启。这是因为Android Activity的默认启动模式(standard)会在每次接收到匹配的Intent时,即使Activity实例已存在,也会在栈顶创建一个新的Activity实例。对于USB_DEVICE_ATTACHED这类外部触发的Intent,系统会尝试启动或重新启动与该Intent关联的Activity,导致不必要的应用状态丢失和用户体验中断。
以下是一个典型的AndroidManifest.xml配置片段,展示了如何监听USB设备连接:
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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>
</application>在这种默认配置下,如果MainActivity正在运行,重新连接USB设备会导致其重启。
要避免应用在USB设备重新连接时重启,同时又能确保在应用未运行时正常启动,关键在于修改Activity的启动模式。android:launchMode="singleTop"是一个理想的选择。
当Activity的启动模式设置为singleTop时:
这种行为完美符合我们的需求:应用未运行时启动,运行中则接收通知而不重启。
在AndroidManifest.xml中,为监听USB连接的Activity添加android:launchMode="singleTop"属性:
<application>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"> <!-- 添加此行 -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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>
</application>仅仅设置launchMode="singleTop"是不够的,我们还需要在Activity中重写onNewIntent()方法来处理接收到的新Intent。当Activity被复用时,onCreate()、onStart()等生命周期方法不会再次被调用,只有onNewIntent()会被触发。
在onNewIntent()方法中,我们可以解析传入的Intent,检查其Action是否为USB_DEVICE_ATTACHED,并执行相应的逻辑,例如更新UI、初始化USB通信或通知用户。
import android.content.Intent;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private UsbManager usbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 假设您的布局文件
Log.d(TAG, "onCreate: Activity created.");
usbManager = (UsbManager) getSystemService(USB_SERVICE);
// 在onCreate中处理初始启动时的Intent
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "onNewIntent: New Intent received.");
// 必须设置新的Intent,否则getIntent()仍然返回旧的Intent
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (intent != null && UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
Log.i(TAG, "USB Device Attached: " + device.getDeviceName());
// 在这里执行您的USB设备初始化或通知逻辑
// 例如:
// setupUsbDevice(device);
// showToast("USB设备 " + device.getProductName() + " 已连接");
} else {
Log.w(TAG, "USB Device Attached intent received, but no device extra.");
}
} else if (intent != null && Intent.ACTION_MAIN.equals(intent.getAction())) {
Log.d(TAG, "Main launcher intent received.");
// 应用通过启动器图标启动
}
}
// 其他生命周期方法和业务逻辑...
}注意事项:
通过将Activity的android:launchMode设置为singleTop,并正确实现onNewIntent()方法,可以有效地解决Android应用在监听USB设备连接时,因设备反复插拔而导致的意外重启问题。这不仅能保持应用的状态,避免不必要的资源消耗,还能显著提升用户体验。在开发与外部硬件交互的Android应用时,理解并合理运用Activity的启动模式是至关重要的。
以上就是避免Android应用因USB设备连接而意外重启的策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号