22

android.view.Windowアプリケーション内のすべての s または装飾ビューをプログラムで列挙することは可能ですか?

Dialogsたとえば、どちらもWindowメインのアクティビティ ウィンドウとは別の新しい で開きます。経由でそれらを見つけることができますDialog.getWindow()が、アクティビティ メニュー ポップアップなどの組み込みコンポーネントを使用してこれを行う方法がわかりません。

ApplicationContext、またはWindowManager、または他の何かから、アプリに関連付けられている Windows を列挙する方法はありますか?

アプリケーションのすべてのウィンドウを で表示できますがadb dumpsys window、ルートを必要とせずにアプリケーション内でこれを行う方法を探しています。

4

6 に答える 6

23

のリフレクションを介してそれを行う方法を見つけました@hidden WindowManagerGlobal。少なくともこれまでのところ、これが android-18 で機能することはわかっています。

private void logRootViews() {
    try {
        Class wmgClass = Class.forName("android.view.WindowManagerGlobal");                        
        Object wmgInstnace = wmgClass.getMethod("getInstance").invoke(null, (Object[])null);

        Method getViewRootNames = wmgClass.getMethod("getViewRootNames"); 
        Method getRootView = wmgClass.getMethod("getRootView", String.class);
        String[] rootViewNames = (String[])getViewRootNames.invoke(wmgInstnace, (Object[])null);

        for(String viewName : rootViewNames) {
            View rootView = (View)getRootView.invoke(wmgInstnace, viewName);
            Log.i(TAG, "Found root view: " + viewName + ": " + rootView);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

出力:

見つかったルート ビュー: com.example.paintsample/com.example.paintsample.PaintSample/android.view.ViewRootImpl@41deeff0: com.android.internal.policy.impl.PhoneWindow$DecorView{41dcc278 VE.... R... .... 0,0-768,1184}

見つかったルート ビュー: PopupWindow:42887380/android.view.ViewRootImpl@42891820: android.widget.PopupWindow$PopupViewContainer{42891450 VE........... 0,0-424,618}

もちろん、より良い方法を見つけることができる人なら誰でも賞金を手に入れることができます:)

于 2013-11-04T20:25:58.720 に答える
15

これが実際の質問に答えているかどうかは完全にはわかりませんが、受け入れられた回答で提案されているように、すべてのルート ビューを取得するより良い方法です。

そこで述べたように、リフレクションのみを使用してこれを達成することもできましたが、このコードはAPI 14以降のすべてのバージョンをサポートしています (以下は確認していません)。

public static List<View> getWindowManagerViews() {
    try {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

            // get the list from WindowManagerImpl.mViews
            Class wmiClass = Class.forName("android.view.WindowManagerImpl");
            Object wmiInstance = wmiClass.getMethod("getDefault").invoke(null);

            return viewsFromWM(wmiClass, wmiInstance);

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {

            // get the list from WindowManagerGlobal.mViews
            Class wmgClass = Class.forName("android.view.WindowManagerGlobal");
            Object wmgInstance = wmgClass.getMethod("getInstance").invoke(null);

            return viewsFromWM(wmgClass, wmgInstance);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return new ArrayList<View>();
}

private static List<View> viewsFromWM(Class wmClass, Object wmInstance) throws Exception {

    Field viewsField = wmClass.getDeclaredField("mViews");
    viewsField.setAccessible(true);
    Object views = viewsField.get(wmInstance);

    if (views instanceof List) {
        return (List<View>) viewsField.get(wmInstance);
    } else if (views instanceof View[]) {
        return Arrays.asList((View[])viewsField.get(wmInstance));
    }

    return new ArrayList<View>();
}
于 2016-12-12T14:27:46.553 に答える