ActivityTaskView
新版使用方法
Github地址:https://github.com/rome753/ActivityTaskView
- 
安装ActivityTaskView release app,启动并给予悬浮窗权限 
 https://github.com/rome753/ActivityTaskView/releases
 或者从 Google Play下载安装。
- 
在你开发的App中加入如下类https://github.com/rome753/ActivityTaskView/blob/master/app/src/main/java/cc/rome753/demo/ActivityTaskHelper.java 
- 
在你开发的App的Application的onCreate()中加入代码 
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTaskInfoList =  am.getRunningTasks(10);
for (RunningTaskInfo runningTaskInfo : runningTaskInfoList) {
    log("id: " + runningTaskInfo.id);
    log("description: " + runningTaskInfo.description);
    log("number of activities: " + runningTaskInfo.numActivities);
    log("topActivity: " + runningTaskInfo.topActivity);
    log("baseActivity: " + runningTaskInfo.baseActivity.toString());
}
该方法只能获取到任务栈的栈顶和栈底的活动,操作起来也麻烦。
总之,目前还没有一种方法能直观地观察Activity任务栈和Activity中的Fragment,像下图这样:
 overview.gif
overview.gif
原理
Android4.0以后Application支持ActivityLifecycleCallbacks和FragmentLifecycleCallbacks的生命周期回调。
ActivityLifecycleCallbacks
private class FragmentLifecycleImpl extends FragmentManager.FragmentLifecycleCallbacks{
        @Override
        public void onFragmentPreAttached(FragmentManager fm, Fragment f, Context context) {
        }
        @Override
        public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {
        }
        @Override
        public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
        }
        @Override
        public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
        }
        @Override
        public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
        }
        @Override
        public void onFragmentStarted(FragmentManager fm, Fragment f) {
            handleFragment(f);
        }
        @Override
        public void onFragmentResumed(FragmentManager fm, Fragment f) {
        }
        @Override
        public void onFragmentPaused(FragmentManager fm, Fragment f) {
        }
        @Override
        public void onFragmentStopped(FragmentManager fm, Fragment f) {
        }
        @Override
        public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {
        }
        @Override
        public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
        }
        @Override
        public void onFragmentDestroyed(FragmentManager fm, Fragment f) {
        }
        @Override
        public void onFragmentDetached(FragmentManager fm, Fragment f) {
        }
    }
同理,在Activity启动时可以给它注册FragmentLifecycleCallbacks来监听Activity中Fragment的变化。不同于Activity在Task中是线性的数据结构,Fragment在Activity中是树状的:一个Activity中可以有多个Fragment,每个Fragment又可以有自己的子Fragment。因此本地需要维护一个树FTree。
FTree.java
WindowManager windowManager = (WindowManager)app.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.START | Gravity.TOP;
params.x = 0;
params.y = app.getResources().getDisplayMetrics().heightPixels;
windowManager.addView(activityTaskView, params);
添加悬浮窗用这个方法就可以了,加上悬浮窗权限。
    float mInnerX;
    float mInnerY;
    long downTime;
    @Override
        public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downTime = System.currentTimeMillis();
                mInnerX = event.getX();
                mInnerY = event.getY();
                postDelayed(this, 300);
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getRawX();
                float y = event.getRawY();
                WindowManager.LayoutParams params = (WindowManager.LayoutParams) getLayoutParams();
                params.x = (int) (x - mInnerX);
                params.y = (int) (y - mInnerY - mStatusHeight);
                updateLayout(params);
                if(Math.abs(event.getX() - mInnerX) > 20
                        || Math.abs(event.getY() - mInnerY) > 20) {
                    removeCallbacks(this);
                }
                break;
            case MotionEvent.ACTION_UP:
                removeCallbacks(this);
                if(System.currentTimeMillis() - downTime < 100
                        && Math.abs(event.getX() - mInnerX) < 20
                        && Math.abs(event.getY() - mInnerY) < 20) {
                    doClick();
                }
                moveToBorder();
                break;
        }
        return true;
    }
    private void doClick() {
        boolean visible = mTaskView.getVisibility() == VISIBLE;
        mTaskView.setVisibility(visible ? GONE : VISIBLE);
        mTinyView.setVisibility(!visible ? GONE : VISIBLE);
    }
    private void doLongClick() {
        Intent intent = new