Seize the day

POST : Android Dev Study

Android getRealSiz(), hasNavigationBar()

getRealSize화면 캡처 앱을 구현하려면 휴대폰의 디스플레이의 크기를 구해야 합니다. 상태바와 하단 네비게이션바까지 포함하는 크기입니다.

	public static void getRealSize(Context context, Point outSize) {
        final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        int realWidth;
        int realHeight;

        if (Build.VERSION.SDK_INT >= 17) {
            //new pleasant way to get real metrics
            DisplayMetrics realMetrics = new DisplayMetrics();
            display.getRealMetrics(realMetrics);
            realWidth = realMetrics.widthPixels;
            realHeight = realMetrics.heightPixels;

        } else if (Build.VERSION.SDK_INT >= 14) {
            //reflection for this weird in-between time
            try {
                Method mGetRawH = Display.class.getMethod("getRawHeight");
                Method mGetRawW = Display.class.getMethod("getRawWidth");
                realWidth = (Integer) mGetRawW.invoke(display);
                realHeight = (Integer) mGetRawH.invoke(display);
            } catch (Exception e) {
                //this may not be 100% accurate, but it's all we've got
                realWidth = display.getWidth();
                realHeight = display.getHeight();
                TraceUtils.d("Display Info", "Couldn't use reflection to get the real display metrics.");
            }

        } else {
            //This should be close, as lower API devices should not have window navigation bars
            realWidth = display.getWidth();
            realHeight = display.getHeight();
        }

        if (Build.MANUFACTURER.equalsIgnoreCase("samsung") && Build.MODEL.startsWith("SM-G950")) {
            realWidth = adjustGalaxyS8Size(realWidth);
            realHeight = adjustGalaxyS8Size(realHeight);
        }

        outSize.x = realWidth;
        outSize.y = realHeight;
    }

    private static int adjustGalaxyS8Size(int size) {
        if (size == 2008) {
            return 2220;
        }
        if (size == 2678) {
            return 2960;
        }
        if (size == 1339) {
            return 1480;
        }
        return size;
    }

갤럭시S8의 경우 사이즈가 실제와 다르게 리턴하기 때문에 보정해 주는 함수 adjustGalaxyS8Size()를 추가했습니다. S8은 화면 해상도를 3개 중에서 선택할 수 있는데 테스트 해 보니 모두 실제와 다르게 응답합니다. 이유는 모르겠습니다. 



hasNavigationBar: 하단 네비게이션바가 있는지 검사하는 코드입니다. 

public static boolean hasNavigationBar(Context context) {
        int navigationBarHeight = getNavigationBarHeight(context);
        if (navigationBarHeight <= 0) {
            return false;
        }

        int id = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
        boolean showNavigationBar = (id > 0 && context.getResources().getBoolean(id));
        if (showNavigationBar) {
            return true;
        }

        boolean hasHardBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
        boolean hasHardHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
        if (!hasHardBackKey && !hasHardHomeKey) {
            return true;
        }

        boolean hasSoftKeys = (context instanceof Activity) && hasNavigationBarBySize((Activity) context);
        if (hasSoftKeys) {
            return true;
        }
        return false;
    }

    private static boolean hasNavigationBarBySize(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display d = activity.getWindowManager().getDefaultDisplay();

            Point realSizePoint = new Point();
            getRealSize(activity, realSizePoint);
            int realWidth = realSizePoint.x;
            int realHeight = realSizePoint.y;

            DisplayMetrics displayMetrics = new DisplayMetrics();
            d.getMetrics(displayMetrics);

            int displayHeight = displayMetrics.heightPixels;
            int displayWidth = displayMetrics.widthPixels;

            return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
        }
        return false;
    }

    public static int getNavigationBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    public static int getNavigationBarWidth(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("navigation_bar_width", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

구글 넥서스 폰의 경우 hasNavigationBarBySize 함수로 체크가 되기 때문에 context는 Activity를 넣어주어야 체크가 됩니다. 간단하게 getNavigationBarHeight() > 0 만으로 다 커버가 될런지는 모르겠습니다. 

top

posted at

2018. 7. 2. 23:39


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크