此问题比较奇葩,复现位置有好几个,大部分都是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<TaskStack> stacks = plan.getAllTaskStacks();
mConfig.launchedWithNoRecentTasks = !plan.hasTasks();

其中是否有任务的判断为上述两行,由于机制特殊,无法在旋转时候监听旋转方法(没具体分析原因),所以只能通过生命周期来控制。

经过log比对,发现按菜单键出现的页面,之后返回首页等操作都不调用onDestory方法,而旋转的时候就会调用,那么解决问题就比较简单了。

 

添加全局变量:

private boolean mLastHasTasks;

在这两行下面添加一行状态记录:

ArrayList<TaskStack> 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();
    }
}

完工。

 

 posted on 2017-03-08 14:27  extfff  阅读(835)  评论(0编辑  收藏  举报