获取Android设备屏幕分辨率

1.Android 4.3引入的wm工具:

a.获取Android设备屏幕分辨率: adb shell wm size

b.获取android设备屏幕密度: adb shell wm density

Wm.java

public class Wm extends BaseCommand {
...
public void onShowUsage(PrintStream out) {
        out.println(
                "usage: wm [subcommand] [options]\n" +
                "       wm size [reset|WxH]\n" +
                "       wm density [reset|DENSITY]\n" +
                "       wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
                "\n" +
                "wm size: return or override display size.\n" +
                "\n" +
                "wm density: override display density.\n" +
                "\n" +
                "wm overscan: set overscan area for display.\n"
                );
    }

    public void onRun() throws Exception {
        mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                        Context.WINDOW_SERVICE));
        if (mWm == null) {
            System.err.println(NO_SYSTEM_ERROR_CODE);
            throw new AndroidException("Can't connect to window manager; is the system running?");
        }

        String op = nextArgRequired();

        if (op.equals("size")) {
            runDisplaySize();
        } else if (op.equals("density")) {
            runDisplayDensity();
        } else if (op.equals("overscan")) {
            runDisplayOverscan();
        } else {
            showError("Error: unknown command '" + op + "'");
            return;
        }
    }

    private void runDisplaySize() throws Exception {
        String size = nextArg();
        int w, h;
        if (size == null) {
            Point initialSize = new Point();
            Point baseSize = new Point();
            try {
                mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
                mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);
                System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y);
                if (!initialSize.equals(baseSize)) {
                    System.out.println("Override size: " + baseSize.x + "x" + baseSize.y);
                }
            } catch (RemoteException e) {
            }
            return;
        } else if ("reset".equals(size)) {
            w = h = -1;
        } else {
            int div = size.indexOf('x');
            if (div <= 0 || div >= (size.length()-1)) {
                System.err.println("Error: bad size " + size);
                return;
            }
            String wstr = size.substring(0, div);
            String hstr = size.substring(div+1);
            try {
                w = Integer.parseInt(wstr);
                h = Integer.parseInt(hstr);
            } catch (NumberFormatException e) {
                System.err.println("Error: bad number " + e);
                return;
            }
        }

        try {
            if (w >= 0 && h >= 0) {
                // TODO(multidisplay): For now Configuration only applies to main screen.
                mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);
            } else {
                mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
            }
        } catch (RemoteException e) {
        }
    }

    private void runDisplayDensity() throws Exception {
        String densityStr = nextArg();
        int density;
        if (densityStr == null) {
            try {
                int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY);
                int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
                System.out.println("Physical density: " + initialDensity);
                if (initialDensity != baseDensity) {
                    System.out.println("Override density: " + baseDensity);
                }
            } catch (RemoteException e) {
            }
            return;
        } else if ("reset".equals(densityStr)) {
            density = -1;
        } else {
            try {
                density = Integer.parseInt(densityStr);
            } catch (NumberFormatException e) {
                System.err.println("Error: bad number " + e);
                return;
            }
            if (density < 72) {
                System.err.println("Error: density must be >= 72");
                return;
            }
        }

        try {
            if (density > 0) {
                // TODO(multidisplay): For now Configuration only applies to main screen.
                mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density);
            } else {
                mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
            }
        } catch (RemoteException e) {
        }
    }
...
View Code

WindowManagerService.java

View Code@Override
    public void getInitialDisplaySize(int displayId, Point size) {
        synchronized (mWindowMap) {
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                synchronized(displayContent.mDisplaySizeLock) {
                    size.x = displayContent.mInitialDisplayWidth;
                    size.y = displayContent.mInitialDisplayHeight;
                }
            }
        }
    }

@Override
    public void getBaseDisplaySize(int displayId, Point size) {
        synchronized (mWindowMap) {
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                synchronized(displayContent.mDisplaySizeLock) {
                    size.x = displayContent.mBaseDisplayWidth;
                    size.y = displayContent.mBaseDisplayHeight;
                }
            }
        }
    }

@Override
    public int getInitialDisplayDensity(int displayId) {
        synchronized (mWindowMap) {
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                synchronized(displayContent.mDisplaySizeLock) {
                    return displayContent.mInitialDisplayDensity;
                }
            }
        }
        return -1;
    }

    @Override
    public int getBaseDisplayDensity(int displayId) {
        synchronized (mWindowMap) {
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                synchronized(displayContent.mDisplaySizeLock) {
                    return displayContent.mBaseDisplayDensity;
                }
            }
        }
        return -1;
    }

@Override
    public void setForcedDisplaySize(int displayId, int width, int height) {
        if (mContext.checkCallingOrSelfPermission(
                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
                PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Must hold permission " +
                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
        }
        if (displayId != Display.DEFAULT_DISPLAY) {
            throw new IllegalArgumentException("Can only set the default display");
        }
        synchronized(mWindowMap) {
            // Set some sort of reasonable bounds on the size of the display that we
            // will try to emulate.
            final int MIN_WIDTH = 200;
            final int MIN_HEIGHT = 200;
            final int MAX_SCALE = 2;
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                width = Math.min(Math.max(width, MIN_WIDTH),
                        displayContent.mInitialDisplayWidth * MAX_SCALE);
                height = Math.min(Math.max(height, MIN_HEIGHT),
                        displayContent.mInitialDisplayHeight * MAX_SCALE);
                setForcedDisplaySizeLocked(displayContent, width, height);
                Settings.Global.putString(mContext.getContentResolver(),
                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
            }
        }
    }

@Override
    public void setForcedDisplayDensity(int displayId, int density) {
        if (mContext.checkCallingOrSelfPermission(
                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
                PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Must hold permission " +
                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
        }
        if (displayId != Display.DEFAULT_DISPLAY) {
            throw new IllegalArgumentException("Can only set the default display");
        }
        synchronized(mWindowMap) {
            final DisplayContent displayContent = getDisplayContentLocked(displayId);
            if (displayContent != null) {
                setForcedDisplayDensityLocked(displayContent, density);
                Settings.Global.putString(mContext.getContentResolver(),
                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
            }
        }
    }

    // displayContent must not be null
    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
        Slog.i(TAG, "Using new display density: " + density);

        synchronized(displayContent.mDisplaySizeLock) {
            displayContent.mBaseDisplayDensity = density;
        }
        reconfigureDisplayLocked(displayContent);
    }

private DisplayContent newDisplayContentLocked(final Display display) {
        DisplayContent displayContent = new DisplayContent(display);
        mDisplayContents.put(display.getDisplayId(), displayContent);
        final Rect rect = new Rect();
        DisplayInfo info = displayContent.getDisplayInfo();
        mDisplaySettings.getOverscanLocked(info.name, rect);
        info.overscanLeft = rect.left;
        info.overscanTop = rect.top;
        info.overscanRight = rect.right;
        info.overscanBottom = rect.bottom;
        mDisplayManagerService.setOverscan(display.getDisplayId(), rect.left, rect.top,
                rect.right, rect.bottom);
        mPolicy.setDisplayOverscan(displayContent.getDisplay(), rect.left, rect.top,
                rect.right, rect.bottom);
        return displayContent;
    }

/**
     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
     * there is a Display for the displayId.
     * @param displayId The display the caller is interested in.
     * @return The DisplayContent associated with displayId or null if there is no Display for it.
     */
    public DisplayContent getDisplayContentLocked(final int displayId) {
        DisplayContent displayContent = mDisplayContents.get(displayId);
        if (displayContent == null) {
            final Display display = mDisplayManager.getDisplay(displayId);
            if (display != null) {
                displayContent = newDisplayContentLocked(display);
            }
        }
        return displayContent;
    }

DisplayContent.java

DisplayManager.java

View Code/**
     * Gets all currently valid logical displays of the specified category.
     * <p>
     * When there are multiple displays in a category the returned displays are sorted
     * of preference.  For example, if the requested category is
     * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays
     * then the displays are sorted so that the first display in the returned array
     * is the most preferred presentation display.  The application may simply
     * use the first display or allow the user to choose.
     * </p>
     *
     * @param category The requested display category or null to return all displays.
     * @return An array containing all displays sorted by order of preference.
     *
     * @see #DISPLAY_CATEGORY_PRESENTATION
     */
    public Display[] getDisplays(String category) {
        final int[] displayIds = mGlobal.getDisplayIds();
        synchronized (mLock) {
            try {
                if (category == null) {
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, -1);
                } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
                }
                return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
            } finally {
                mTempDisplays.clear();
            }
        }
    }

    private void addMatchingDisplaysLocked(
            ArrayList<Display> displays, int[] displayIds, int matchType) {
        for (int i = 0; i < displayIds.length; i++) {
            Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
            if (display != null
                    && (matchType < 0 || display.getType() == matchType)) {
                displays.add(display);
            }
        }
    }

2.显示区域分为应用显示区域和真实显示区域。

a.应用显示区域不包括系统点缀,它可能比真实显示区域小因为系统减掉了点缀元素的空间如导航栏(隐藏/显示导航栏得到的高度不同)

View CodeDisplayMetrics metrics = new DisplayMetrics();
Display displaymetrics = getWindowManager().getDefaultDisplay().getMetrics(metrics);

int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
float density = displaymetrics.density;
int densityDpi = displaymetrics.densityDpi;

Display.java

View Code/**
     * Gets display metrics that describe the size and density of this display.
     * <p>
     * The size is adjusted based on the current rotation of the display.
     * </p><p>
     * The size returned by this method does not necessarily represent the
     * actual raw size (native resolution) of the display.  The returned size may
     * be adjusted to exclude certain system decor elements that are always visible.
     * It may also be scaled to provide compatibility with older applications that
     * were originally designed for smaller displays.
     * </p>
     *
     * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
     */
    public void getMetrics(DisplayMetrics outMetrics) {
        synchronized (this) {
            updateDisplayInfoLocked();
            mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
        }
    }

/**
     * Gets display metrics based on the real size of this display.
     * <p>
     * The size is adjusted based on the current rotation of the display.
     * </p><p>
     * The real size may be smaller than the physical size of the screen when the
     * window manager is emulating a smaller display (using adb shell am display-size).
     * </p>
     *
     * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
     */
    public void getRealMetrics(DisplayMetrics outMetrics) {
        synchronized (this) {
            updateDisplayInfoLocked();
            mDisplayInfo.getLogicalMetrics(outMetrics, null);
        }
    }

    private void updateDisplayInfoLocked() {
        // Note: The display manager caches display info objects on our behalf.
        DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
        if (newInfo == null) {
            // Preserve the old mDisplayInfo after the display is removed.
            if (mIsValid) {
                mIsValid = false;
                if (DEBUG) {
                    Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
                }
            }
        } else {
            // Use the new display info.  (It might be the same object if nothing changed.)
            mDisplayInfo = newInfo;
            if (!mIsValid) {
                mIsValid = true;
                if (DEBUG) {
                    Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
                }
            }
        }
    }

DisplayInfo.java

View Code/**
 * Describes the characteristics of a particular logical display.
 * @hide
 */
public final class DisplayInfo implements Parcelable {
...

/**
     * The width of the portion of the display that is available to applications, in pixels.
     * Represents the size of the display minus any system decorations.
     */
    public int appWidth;

    /**
     * The height of the portion of the display that is available to applications, in pixels.
     * Represents the size of the display minus any system decorations.
     */
    public int appHeight;
...
/**
     * The logical width of the display, in pixels.
     * Represents the usable size of the display which may be smaller than the
     * physical size when the system is emulating a smaller display.
     */
    public int logicalWidth;

    /**
     * The logical height of the display, in pixels.
     * Represents the usable size of the display which may be smaller than the
     * physical size when the system is emulating a smaller display.
     */
    public int logicalHeight;
...
public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
        @Override
        public DisplayInfo createFromParcel(Parcel source) {
            return new DisplayInfo(source);
        }

        @Override
        public DisplayInfo[] newArray(int size) {
            return new DisplayInfo[size];
        }
    };
...
private DisplayInfo(Parcel source) {
        readFromParcel(source);
    }
...
 public void readFromParcel(Parcel source) {
        layerStack = source.readInt();
        flags = source.readInt();
        type = source.readInt();
        address = source.readString();
        name = source.readString();
        appWidth = source.readInt();
        appHeight = source.readInt();
        smallestNominalAppWidth = source.readInt();
        smallestNominalAppHeight = source.readInt();
        largestNominalAppWidth = source.readInt();
        largestNominalAppHeight = source.readInt();
        logicalWidth = source.readInt();
        logicalHeight = source.readInt();
        overscanLeft = source.readInt();
        overscanTop = source.readInt();
        overscanRight = source.readInt();
        overscanBottom = source.readInt();
        rotation = source.readInt();
        refreshRate = source.readFloat();
        logicalDensityDpi = source.readInt();
        physicalXDpi = source.readFloat();
        physicalYDpi = source.readFloat();
    }


public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
        getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
    }

public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
        getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
    }

private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
            int width, int height) {
        outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;

        outMetrics.density = outMetrics.noncompatDensity =
                logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;

        if (cih != null) {
            CompatibilityInfo ci = cih.getIfNeeded();
            if (ci != null) {
                ci.applyToDisplayMetrics(outMetrics);
            }
        }
    }

b.真实显示区域包括系统点缀,但它有可能比物理显示小当窗口管理器模拟更小显示(如使用adb shell am display-size)时

View CodeDisplay d = getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = d.getMetrics(new DisplayMetrics());

int ver = Build.VERSION.SDK_INT;
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
if (Build.VERSION.SDK_INT = 13)
try {
    widthPixels = (Integer) Display.class.getMethod("getRealWidth").invoke(d);
    heightPixels = (Integer) Display.class.getMethod("getRealHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
    widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
    heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
    //Point realSize = new Point();
    //Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
    //widthPixels = realSize.x;
    //heightPixels = realSize.y;
    DisplayMetrics realMetrics = d.getRealMetrics(new DisplayMetrics());
    widthPixels = realMetrics.widthPixels;
    heightPixels = realMetrics.heightPixels;
} catch (Exception ignored) {
}

转载于:https://www.cnblogs.com/fanfeng/p/3263853.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值