在Android上检测4K UHD屏幕

Cob*_*bar 10 android android-tv

我试图检测设备何时能够以4K UHD(3840x2160)分辨率输出.许多设备(如nVidia Shield TV和Sony Xperia Z5 Premium)都会报告它们以1080p运行,即使它们具有UHD功能,因为它们默认为非视频布局的1080p输出.我需要一些方法来检测它们是否能够区分它们以及像Nexus Player这样的非4K设备.

这是我用来确定当前分辨率的代码:

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
Run Code Online (Sandbox Code Playgroud)

在Shield TV上,即使ExoPlayer报告它在3840x2160输出视频,也会一直返回1920x1080.

Jua*_*lez 5

更新:这已从 ExoPlayer 1.5.1 开始修复(参见https://github.com/google/ExoPlayer/commit/79055066813123c939c29e5a5e223a5ff043b91e


我跟进了 ExoPlayer 的开发人员并找到了答案:

可靠检测 4K 设备的唯一方法是使用Device.Mode仅在 api 级别 23+ 中可用的方法。请参阅此处的 Android M 说明:

https://developer.android.com/preview/api-overview.html#4K-display

以及该课程的文档:

https://developer.android.com/reference/android/view/Display.Mode.html#getPhysicalWidth()

至于ExoPlayer它没有实现这个代码,从当前版本(1.4.2)开始,但这可能会改变。看:

https://github.com/google/ExoPlayer/issues/800

最后来回答这个问题,现在检测 4K 的正确方法是这样的:

/**
 * Used to check if the connected device support UHD (3840x2160)
 *
 * Note that this call will fail to identify UHD devices on api level bellow 23 (M)
 *
 * @return 1 if device is UHD, 0 otherwise
 */
public int isUHD(){
    Display display = getActivity().getWindowManager().getDefaultDisplay();
    Point displaySize = getDisplaySize(display);
    return (displaySize.x >= 3840 && displaySize.y >= 2160) ? 1 : 0;
}

/**
 * Convenience function that forks to the different ways to obatin the Display size across Android versions
 *
 * @param display Display instance to obtain information from
 *
 * @return Point a Point describing the Display size
 */
private static Point getDisplaySize(Display display) {
    Point displaySize = new Point();
    if(Util.SDK_INT >= 23){
        getDisplaySizeV23(display, displaySize);
    }else if(Util.SDK_INT >= 17) {
        getDisplaySizeV17(display, displaySize);
    } else if(Util.SDK_INT >= 16) {
        getDisplaySizeV16(display, displaySize);
    } else {
        getDisplaySizeV9(display, displaySize);
    }
    return displaySize;
}

@TargetApi(23)
private static void getDisplaySizeV23(Display display, Point outSize){
    Display.Mode[] modes = display.getSupportedModes();
    if(modes.length > 0){
        Display.Mode mode = modes[0];
        outSize.x = mode.getPhysicalWidth();
        outSize.y = mode.getPhysicalHeight();
    }
}

@TargetApi(17)
private static void getDisplaySizeV17(Display display, Point outSize) {
    display.getRealSize(outSize);
}

@TargetApi(16)
private static void getDisplaySizeV16(Display display, Point outSize) {
    display.getSize(outSize);
}

private static void getDisplaySizeV9(Display display, Point outSize) {
    outSize.x = display.getWidth();
    outSize.y = display.getHeight();
}
Run Code Online (Sandbox Code Playgroud)

这将在小于 23 的 api 上给出错误的结果。