How to check if the current activity has a dialog in front?

后端 未结 8 1878
自闭症患者
自闭症患者 2021-02-05 09:37

I am using a third-party library and sometimes it pops up a dialog. Before I finish the current activity, I want to check whether there is a dialog popped up in the current con

8条回答
  •  臣服心动
    2021-02-05 10:31

    This uses reflection and hidden APIs to get the currently active view roots. If an alert dialog shows this will return an additional view root. But careful as even a toast popup will return an additional view root.

    I've confirmed compatibility from Android 4.1 to Android 6.0 but of course this may not work in earlier or later Android versions.

    I've not checked the behavior for multi-window modes.

    @SuppressWarnings("unchecked")
    public static List getViewRoots() {
    
        List viewRoots = new ArrayList<>();
    
        try {
            Object windowManager;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                windowManager = Class.forName("android.view.WindowManagerGlobal")
                        .getMethod("getInstance").invoke(null);
            } else {
                Field f = Class.forName("android.view.WindowManagerImpl")
                        .getDeclaredField("sWindowManager");
                f.setAccessible(true);
                windowManager = f.get(null);
            }
    
            Field rootsField = windowManager.getClass().getDeclaredField("mRoots");
            rootsField.setAccessible(true);
    
            Field stoppedField = Class.forName("android.view.ViewRootImpl")
                    .getDeclaredField("mStopped");
            stoppedField.setAccessible(true);
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                List viewParents = (List) rootsField.get(windowManager);
                // Filter out inactive view roots
                for (ViewParent viewParent : viewParents) {
                    boolean stopped = (boolean) stoppedField.get(viewParent);
                    if (!stopped) {
                        viewRoots.add(viewParent);
                    }
                }
            } else {
                ViewParent[] viewParents = (ViewParent[]) rootsField.get(windowManager);
                // Filter out inactive view roots
                for (ViewParent viewParent : viewParents) {
                    boolean stopped = (boolean) stoppedField.get(viewParent);
                    if (!stopped) {
                        viewRoots.add(viewParent);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return viewRoots;
    }
    

提交回复
热议问题