2016/12/29

How to correctly get screenshot from MediaProjection without black area

Step 1 Request a MediaProjection object
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(projectionManager.createScreenCaptureIntent(), /*YOUR_REQUEST_CODE*/);

Step 2 Once user submit the permission request dialog, you can get a MediaProjection object in
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
MediaProjection mProjection = projectionManager.getMediaProjection(resultCode, data);

Step 3 Create an ImageReader and a screen-size-fit VirtualDisplay
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
Point size = new Point();
display.getRealSize(size);
final int mWidth = size.x;
final int mHeight = size.y;
int mDensity = metrics.densityDpi;

final ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);

final Handler handler = new Handler();

int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
mProjection.createVirtualDisplay("screen-mirror", mWidth, mHeight, mDensity, flags, mImageReader.getSurface(), null, handler);

Step 4 Get screenshot in OnImageAvailableListener
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                reader.setOnImageAvailableListener(null, handler);

                Image image = reader.acquireLatestImage();

                final Image.Plane[] planes = image.getPlanes();
                final ByteBuffer buffer = planes[0].getBuffer();
    
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * metrics.widthPixels;
                // create bitmap
                Bitmap bmp = Bitmap.createBitmap(metrics.widthPixels + (int) ((float) rowPadding / (float) pixelStride), metrics.heightPixels, Bitmap.Config.ARGB_8888);
                bmp.copyPixelsFromBuffer(buffer);

                image.close();
                reader.close();

                Bitmap realSizeBitmap = Bitmap.createBitmap(bmp, 0, 0, metrics.widthPixels, bmp.getHeight());
                bmp.recycle();
    
                /* do something with [realSizeBitmap] */
            }
        }, handler);

For full example code you can found at https://github.com/firemaples/EverTranslator/blob/master/deprecated/src/main/java/tw/firemaples/onscreenocr/screenshot/ScreenshotHandler.java
Kotlin version: https://github.com/firemaples/EverTranslator/blob/master/main/src/main/java/tw/firemaples/onscreenocr/screenshot/ScreenExtractor.kt

Reference:

http://binwaheed.blogspot.tw/2015/03/how-to-correctly-take-screenshot-using.html

1 則留言: