在Android 9.0的项目中,测试工程师验证问题时插入某些USB的无线鼠标,会导致当前的APK会销毁然后重启一次,重新走一次生命周期。
为什么会重启?
我们大概率的知道,一般App重启大致有如下原因:
机器状态改变了(比如改变语言),导致Activity重启了
不过,由于日志中没有异常日志,因此考虑后面一种情况。
下面是在《插入无线鼠标Android应用重启问题》
后面发现插入有问题的USB无线收发器,会生成2个设备,一个鼠标和一个键盘。没错,这是键鼠套装一体的无线收发器,正是这个键盘导致出现了现在的这个现象,而有些无线鼠标的无线收发器不是键鼠套装,所有只会有1个鼠标设备,所以插上去没有问题。
这里更加肯定了我的猜想[机器状态改变了(比如改变语音),导致Activity重启了]。
特意打印了一下Activity的生命周期的日志,发现Activity被销毁,然后重新启动了。
Android文档中有如下说明(前面《AndroidManifest.xml的configChanges配置简介》中也讲解过)
如果我们AndroidManifest.xml中的Activity中的android:configChanges申明了对应的属性,当属性改变时Activity不会重启且调用onConfigurationChanged()
因此解决,这个问题就是我们在AndroidManifest.xml中申明一下插入USB的无线鼠标后会改变的状态值即可。
但,我们不知道到底改变了哪一个值。为了验证,我们可以通过下面的方式做一下试验,然后找出幕后的凶手。
磨刀呼呼向猪羊。
第一步:AndroidManifest.xml的MainActivity的configChanges申明加入可能改变的状态
android:configChanges="orientation|uiMode|keyboard|keyboardHidden|fontScale|touchscreen|navigation|screenLayout|colorMode"
第二步:MainActivity中实现onConfigurationChanged,并添加如下打印。
@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);Log.d(TAG, "onConfigurationChanged keyboard : " + newConfig.keyboard);Log.d(TAG, "onConfigurationChanged densityDpi : " + newConfig.densityDpi);Log.d(TAG, "onConfigurationChanged fontScale : " + newConfig.fontScale);Log.d(TAG, "onConfigurationChanged hardKeyboardHidden : " + newConfig.hardKeyboardHidden);Log.d(TAG, "onConfigurationChanged keyboardHidden : " + newConfig.keyboardHidden);Log.d(TAG, "onConfigurationChanged mcc : " + newConfig.mcc);Log.d(TAG, "onConfigurationChanged mnc : " + newConfig.mnc);Log.d(TAG, "onConfigurationChanged navigation : " + newConfig.navigation);Log.d(TAG, "onConfigurationChanged navigationHidden : " + newConfig.navigationHidden);Log.d(TAG, "onConfigurationChanged orientation : " + newConfig.orientation);Log.d(TAG, "onConfigurationChanged screenHeightDp : " + newConfig.screenHeightDp);Log.d(TAG, "onConfigurationChanged screenLayout : " + newConfig.screenLayout);Log.d(TAG, "onConfigurationChanged smallestScreenWidthDp : " + newConfig.smallestScreenWidthDp);Log.d(TAG, "onConfigurationChanged touchscreen : " + newConfig.touchscreen);Log.d(TAG, "onConfigurationChanged uiMode : " + newConfig.uiMode);Log.d(TAG, "onConfigurationChanged locale : " + newConfig.locale)
第三步:插拔USB无线收发器
下面是插拔的日志打印。
# 插入onConfigurationChanged keyboard : 2onConfigurationChanged densityDpi : 160onConfigurationChanged fontScale : 1.0onConfigurationChanged hardKeyboardHidden : 1onConfigurationChanged keyboardHidden : 1onConfigurationChanged mcc : 460onConfigurationChanged mnc : 7onConfigurationChanged navigation : 2onConfigurationChanged navigationHidden : 1onConfigurationChanged orientation : 2onConfigurationChanged screenHeightDp : 670onConfigurationChanged screenLayout : 268435812onConfigurationChanged smallestScreenWidthDp : 720onConfigurationChanged touchscreen : 3onConfigurationChanged uiMode : 17onConfigurationChanged locale : zh_CN# 拔出onConfigurationChanged keyboard : 1onConfigurationChanged densityDpi : 160onConfigurationChanged fontScale : 1.0onConfigurationChanged hardKeyboardHidden : 2onConfigurationChanged keyboardHidden : 1onConfigurationChanged mcc : 460onConfigurationChanged mnc : 7onConfigurationChanged navigation : 1onConfigurationChanged navigationHidden : 2onConfigurationChanged orientation : 2onConfigurationChanged screenHeightDp : 670onConfigurationChanged screenLayout : 268435812onConfigurationChanged smallestScreenWidthDp : 720onConfigurationChanged touchscreen : 3onConfigurationChanged uiMode : 17onConfigurationChanged locale : zh_CN
日志中出现navigation、navigationHidden、keyboard、hardKeyboardHidden几个的状态改变了。
从上面日志中知道navigation、navigationHidden、keyboard、hardKeyboardHidden几个的状态发生了改变,加上我们没有配置这几个状态的监听,所以Activity被重启了一次。
因此,我们在AndroidManifest.xml中的Activity配置为如下:
android:configChanges="keyboard|navigation|keyboardHidden"