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 만으로 다 커버가 될런지는 모르겠습니다.