/** Takes a screenshot of the current display and shows an animation. */ void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) { // We need to orient the screenshot correctly (and the Surface api seems to take screenshots // only in the natural orientation of the device :!) mDisplay.getRealMetrics(mDisplayMetrics); float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; // float degrees = getDegreesForRotation(mDisplay.getRotation()); int value = mDisplay.getRotation(); String hwRotation = SystemProperties.get("ro.sf.hwrotation", "0"); if (hwRotation.equals("270") || hwRotation.equals("90")) { value = (value + 3) % 4; } float degrees = getDegreesForRotation(value); boolean requiresRotation = (degrees > 0); if (requiresRotation) { // Get the dimensions of the device in its native orientation mDisplayMatrix.reset(); mDisplayMatrix.preRotate(-degrees); mDisplayMatrix.mapPoints(dims); dims[0] = Math.abs(dims[0]); dims[1] = Math.abs(dims[1]); } // Take the screenshot mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]); if (mScreenBitmap == null) { notifyScreenshotError(mContext, mNotificationManager); finisher.run(); return; } if (requiresRotation) { // Rotate the screenshot to the current orientation Bitmap ss = Bitmap.createBitmap( mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(ss); c.translate(ss.getWidth() / 2, ss.getHeight() / 2); c.rotate(degrees); c.translate(-dims[0] / 2, -dims[1] / 2); c.drawBitmap(mScreenBitmap, 0, 0, null); c.setBitmap(null); mScreenBitmap = ss; } // Optimizations mScreenBitmap.setHasAlpha(false); mScreenBitmap.prepareToDraw(); // Start the post-screenshot animation startAnimation( finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, statusBarVisible, navBarVisible); }
/** Returns a screenshot of the current display contents. */ Bitmap createScreenshot() { // We need to orient the screenshot correctly (and the Surface api seems to // take screenshots only in the natural orientation of the device :!) mDisplay.getRealMetrics(mDisplayMetrics); boolean hasNavBar = mContext.getResources().getBoolean(com.android.internal.R.bool.config_showNavigationBar); float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; float degrees = getDegreesForRotation(mDisplay.getRotation()); final int statusBarHeight = mContext .getResources() .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); // Navbar has different sizes, depending on orientation final int navBarHeight = hasNavBar ? mContext .getResources() .getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height) : 0; final int navBarWidth = hasNavBar ? mContext .getResources() .getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width) : 0; boolean requiresRotation = (degrees > 0); if (requiresRotation) { // Get the dimensions of the device in its native orientation mDisplayMatrix.reset(); mDisplayMatrix.preRotate(-degrees); mDisplayMatrix.mapPoints(dims); dims[0] = Math.abs(dims[0]); dims[1] = Math.abs(dims[1]); } Bitmap bitmap = Surface.screenshot((int) dims[0], (int) dims[1]); // Bail if we couldn't take the screenshot if (bitmap == null) { return null; } if (requiresRotation) { // Rotate the screenshot to the current orientation Bitmap ss = Bitmap.createBitmap( mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(ss); c.translate(ss.getWidth() / 2, ss.getHeight() / 2); c.rotate(360f - degrees); c.translate(-dims[0] / 2, -dims[1] / 2); c.drawBitmap(bitmap, 0, 0, null); bitmap = ss; } // TODO this is somewhat device-specific; need generic solution. // Crop off the status bar and the nav bar // Portrait: 0, statusBarHeight, width, height - status - nav // Landscape: 0, statusBarHeight, width - navBar, height - status int newLeft = 0; int newTop = statusBarHeight; int newWidth = bitmap.getWidth(); int newHeight = bitmap.getHeight(); if (bitmap.getWidth() < bitmap.getHeight()) { // Portrait mode: status bar is at the top, navbar bottom, width unchanged newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight; } else { // Landscape mode: status bar is at the top, navbar right newHeight = bitmap.getHeight() - statusBarHeight; newWidth = bitmap.getWidth() - navBarWidth; } bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight); return bitmap; }