此问题比较奇葩,复现位置有好几个,大部分都是settings。
例如:连接usb后点击通知栏的USB连接选项,然后再直接按home键,或者蓝牙接收点击之后有个弹出框,在按home键。
解决方案如下(原本想跟入到底层看看到底什么原因,结果发现任务列表是从ActivityManagerNative.java类中取得,故不走此胡同):
分析:
\frameworks\base\packages\SystemUI\src\com\android\systemui\recents\RecentsActivity.java
发现手机按下菜单键之后就会触发此页面开启。
具体发起人为:
./src/com/android/systemui/recents/Recents.java
具体参见:
void startAlternateRecentsActivity(ActivityManager.RunningTaskInfo topTask,
ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
TaskStackViewLayoutAlgorithm.VisibilityReport vr)
过程不细说,核心关键为:为什么启动时候没有任务,而旋转之后就出现,经过不断抓取log后发现:
RecentsActivity.java类中有个
RecentsConfiguration mConfig;
此全局变量中有个很关键的变量launchedFromHome,如果当前没有任务,每次按菜单键启动,那么此变量一定是true,如果旋转那么必定为false。
如果有任务,那么必定都是false。
具体过程不做描述,想要了解过程的可以参见Recents类的startRecentsActivity方法。
分析问题最后结论为:只要保证在旋转的时候launchedFromHome可以正确判断即可解决问题(后续变化改动都在RecentsActivity类)
那么第一步,判断上一次旋转屏是否有任务:
参考:
void updateRecentsTasks()
此方法为每次开启最近任务时候都会调用到
ArrayList stacks = plan.getAllTaskStacks();
mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
其中是否有任务的判断为上述两行,由于机制特殊,无法在旋转时候监听旋转方法(没具体分析原因),所以只能通过生命周期来控制。
经过log比对,发现按菜单键出现的页面,之后返回首页等操作都不调用onDestory方法,而旋转的时候就会调用,那么解决问题就比较简单了。
添加全局变量:
private boolean mLastHasTasks;
在这两行下面添加一行状态记录:
ArrayList stacks = plan.getAllTaskStacks();
mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
mLastHasTasks = mConfig.launchedWithNoRecentTasks; //add
在onDestory方法内添加:
@Override
protected void onDestroy() {
super.onDestroy();
if(mLastHasTasks){ //add
mConfig.launchedFromHome = true; //add
} //add
// Unregister the system broadcast receivers
unregisterReceiver(mSystemBroadcastReceiver);
// Stop listening for widget package changes if there was one bound
if (Constants.DebugFlags.App.EnableSearchBar) {
mAppWidgetHost.stopListening();
}
}
完工。