前言
在Android 9.0的项目中,测试工程师验证问题时插入某些USB的无线鼠标,会导致当前的APK会销毁然后重启一次,重新走一次生命周期。
Activity为啥会重启?
为什么会重启?
我们大概率的知道,一般App重启大致有如下原因:
- 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,并添加如下打印。
@Override public 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 : 2 onConfigurationChanged densityDpi : 160 onConfigurationChanged fontScale : 1.0 onConfigurationChanged hardKeyboardHidden : 1 onConfigurationChanged keyboardHidden : 1 onConfigurationChanged mcc : 460 onConfigurationChanged mnc : 7 onConfigurationChanged navigation : 2 onConfigurationChanged navigationHidden : 1 onConfigurationChanged orientation : 2 onConfigurationChanged screenHeightDp : 670 onConfigurationChanged screenLayout : 268435812 onConfigurationChanged smallestScreenWidthDp : 720 onConfigurationChanged touchscreen : 3 onConfigurationChanged uiMode : 17 onConfigurationChanged locale : zh_CN # 拔出 onConfigurationChanged keyboard : 1 onConfigurationChanged densityDpi : 160 onConfigurationChanged fontScale : 1.0 onConfigurationChanged hardKeyboardHidden : 2 onConfigurationChanged keyboardHidden : 1 onConfigurationChanged mcc : 460 onConfigurationChanged mnc : 7 onConfigurationChanged navigation : 1 onConfigurationChanged navigationHidden : 2 onConfigurationChanged orientation : 2 onConfigurationChanged screenHeightDp : 670 onConfigurationChanged screenLayout : 268435812 onConfigurationChanged smallestScreenWidthDp : 720 onConfigurationChanged touchscreen : 3 onConfigurationChanged uiMode : 17 onConfigurationChanged locale : zh_CN
日志中出现navigation、navigationHidden、keyboard、hardKeyboardHidden几个的状态改变了。
解决方式
从上面日志中知道navigation、navigationHidden、keyboard、hardKeyboardHidden几个的状态发生了改变,加上我们没有配置这几个状态的监听,所以Activity被重启了一次。
因此,我们在AndroidManifest.xml中的Activity配置为如下:
android:configChanges="keyboard|navigation|keyboardHidden"
参考文章