android.media.projection.MediaProjection Java Examples

The following examples show how to use android.media.projection.MediaProjection. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: HyperionScreenService.java    From hyperion-android-grabber with MIT License 6 votes vote down vote up
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void startScreenRecord(final Intent intent) {
    if (DEBUG) Log.v(TAG, "Start screen recorder");
    final int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, 0);
    // get MediaProjection
    final MediaProjection projection = mMediaProjectionManager.getMediaProjection(resultCode, intent);
    WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    if (projection != null && window != null) {
        _mediaProjection = projection;
        final DisplayMetrics metrics = new DisplayMetrics();
        window.getDefaultDisplay().getRealMetrics(metrics);
        final int density = metrics.densityDpi;
        HyperionGrabberOptions options = new HyperionGrabberOptions(mHorizontalLEDCount,
                mVerticalLEDCount, mFrameRate, mSendAverageColor);
        if (DEBUG) Log.v(TAG, "Starting the recorder");
        mHyperionEncoder = new HyperionScreenEncoder(mHyperionThread.getReceiver(),
                projection, metrics.widthPixels, metrics.heightPixels,
                density, options);
        mHyperionEncoder.sendStatus();
    }
}
 
Example #2
Source File: ScreenRecordByCodecActivity.java    From ScreenCapture with MIT License 6 votes vote down vote up
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_MEDIA_PROJECTION) {
        // NOTE: Should pass this result data into a Service to run ScreenRecorder.
        // The following codes are merely exemplary.

        MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
        if (mediaProjection == null) {
            Log.e("@@", "media projection is null");
            return;
        }

        mMediaProjection = mediaProjection;
        mMediaProjection.registerCallback(mProjectionCallback, new Handler());
        startCapturing(mediaProjection);
    }
}
 
Example #3
Source File: ScreenRecordByCodecActivity.java    From ScreenCapture with MIT License 6 votes vote down vote up
private void startCapturing(MediaProjection mediaProjection) {
    VideoEncodeConfig video = createVideoConfig();
    AudioEncodeConfig audio = createAudioConfig(); // audio can be null
    if (video == null) {
        toast(getString(R.string.create_screenRecorder_failure));
        return;
    }

    File dir = getSavingDir();
    if (!dir.exists() && !dir.mkdirs()) {
        cancelRecorder();
        return;
    }
    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US);
    final File file = new File(dir, "Screenshots-" + format.format(new Date())
            + "-" + video.width + "x" + video.height + ".mp4");
    Log.d("@@", "Create recorder with :" + video + " \n " + audio + "\n " + file);
    mRecorder = newRecorder(mediaProjection, video, audio, file);
    if (hasPermissions()) {
        startRecorder();
    } else {
        cancelRecorder();
    }
}
 
Example #4
Source File: ScreenRecordByCodecActivity.java    From ScreenCapture with MIT License 6 votes vote down vote up
private VirtualDisplay getOrCreateVirtualDisplay(MediaProjection mediaProjection, VideoEncodeConfig config) {
    if (mVirtualDisplay == null) {
        mVirtualDisplay = mediaProjection.createVirtualDisplay("ScreenRecorder-display0",
                config.width, config.height, 1 /*dpi*/,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
                null /*surface*/, null, null);
    } else {
        // resize if size not matched
        Point size = new Point();
        mVirtualDisplay.getDisplay().getSize(size);
        if (size.x != config.width || size.y != config.height) {
            mVirtualDisplay.resize(config.width, config.height, 1);
        }
    }
    return mVirtualDisplay;
}
 
Example #5
Source File: ScreenRecorderService.java    From DoraemonKit with Apache License 2.0 6 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    try {
        createNotificationChannel();
        //Android Q 存在兼容性问题
        MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) intent.getParcelableExtra("data"));
        ColorPickManager.getInstance().setMediaProjection(mediaProjection);
        if (ColorPickManager.getInstance().getColorPickerDokitView() != null) {
            ColorPickManager.getInstance().getColorPickerDokitView().onScreenServiceReady();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return super.onStartCommand(intent, flags, startId);
}
 
Example #6
Source File: ImageCapture.java    From DoraemonKit with Apache License 2.0 6 votes vote down vote up
/**
 *
 */
void initImageRead(MediaProjection mediaProjection) {
    if (mediaProjection == null) {
        LogHelper.e(TAG, "mediaProjection == null");
        return;
    }
    int width = UIUtils.getWidthPixels();
    int height = UIUtils.getRealHeightPixels();
    int dpi = UIUtils.getDensityDpi();
    mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
    /**
     * 获取getSurface
     */
    mediaProjection.createVirtualDisplay("ScreenCapture",
            width, height, dpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mImageReader.getSurface(), null, null);
}
 
Example #7
Source File: VideoSender.java    From AndroidScreenShare with Apache License 2.0 6 votes vote down vote up
/**
 *
 * @param st 发送线程
 * @param mp  MediaProjection
 * @param width 视频宽度 1080
 * @param height 视频高度 1920
 * @param videoBitrate 视频 比特率  16777216
 * @param videoFrameRate 视频 帧率 24
 */
public VideoSender(SocketServerThread st, MediaProjection mp,
                   int width,int height,
                   int videoBitrate,int videoFrameRate
){

    socketServerThread=st;
    this.width=width;
    this.height=height;
    this.videoBitrate=videoBitrate;
    this.videoFrameRate=videoFrameRate;

    this.mediaReader =new MediaReader(width,height,videoBitrate,
            videoFrameRate,this,mp);
    mediaReader.startEncode();
}
 
Example #8
Source File: MediaProjectionActivity.java    From AndroidScreenShare with Apache License 2.0 6 votes vote down vote up
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
        case REQUEST_MEDIA_PROJECTION:

            if (resultCode == RESULT_OK && data != null) {
                MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
                if (mediaProjection == null) {
                    Log.e("@@", "media projection is null");
                    return;
                }
                MyApplication.setMediaProjection(mediaProjection);
                onResultCode();

                buttonstart.setText(R.string.app_but_stop);
                buttonstart.setEnabled(true);
            }else {
                buttonstart.setText(R.string.app_but_shar);
                buttonstart.setEnabled(true);
            }
            break;
    }

}
 
Example #9
Source File: OwtScreenCapturer.java    From owt-client-android with Apache License 2.0 5 votes vote down vote up
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public OwtScreenCapturer(Intent data, int width, int height) {
    super(data, new MediaProjection.Callback() {
        @Override
        public void onStop() {
            super.onStop();
        }
    });
    this.width = width;
    this.height = height;
}
 
Example #10
Source File: ScreenCastManager.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
/**
 * MediaProjection の後始末を行います.
 */
synchronized void clean() {
    MediaProjection projection = mMediaProjection;
    if (projection != null) {
        projection.stop();
        mMediaProjection = null;
    }
}
 
Example #11
Source File: AbstractScreenCast.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
AbstractScreenCast(Context context, MediaProjection mediaProjection, int width, int height) {
    mContext = context;
    mMediaProjection = mediaProjection;

    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    mDisplayDensityDpi = metrics.densityDpi;
    mWidth = width;
    mHeight = height;
}
 
Example #12
Source File: HyperionScreenEncoder.java    From hyperion-android-grabber with MIT License 5 votes vote down vote up
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
HyperionScreenEncoder(final HyperionThread.HyperionThreadListener listener,
                       final MediaProjection projection, final int width, final int height,
                       final int density, HyperionGrabberOptions options) {
    super(listener, projection, width, height, density, options);

    try {
        prepare();
    } catch (MediaCodec.CodecException e) {
        e.printStackTrace();
    }
}
 
Example #13
Source File: ScreenCapturer.java    From ScreenCapture with MIT License 5 votes vote down vote up
public ScreenCapturer(Context context, MediaProjection mediaProjection, String savePath) {
    sMediaProjection = mediaProjection;
    mContext = context;

    isScreenCaptureStarted = false;

    new Thread() {
        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler();
            Looper.loop();
        }
    }.start();


    if (TextUtils.isEmpty(savePath)) {
        File externalFilesDir = mContext.getExternalFilesDir(null);
        Log.d("WOW", "externalFilesDir:" + externalFilesDir.getAbsolutePath());
        if (externalFilesDir != null) {
            STORE_DIR = externalFilesDir.getAbsolutePath() + "/myScreenshots";
        } else {
            Toast.makeText(mContext, "No save path assigned!", Toast.LENGTH_SHORT);
        }
    } else {
        STORE_DIR = savePath;
    }
}
 
Example #14
Source File: ScreenCapturer.java    From habpanelviewer with GNU General Public License v3.0 5 votes vote down vote up
ScreenCapturer(MediaProjection projection, int width, int height, int density) {
    mHandler = new Handler();
    mProjection = projection;
    mWidth = width;
    mHeight = height;
    mDensity = density;
}
 
Example #15
Source File: MainActivity.java    From habpanelviewer with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == Constants.REQUEST_PICK_APPLICATION && resultCode == RESULT_OK) {
        startActivity(data);
    } else if (requestCode == Constants.REQUEST_MEDIA_PROJECTION) {

        boolean allowCapture = resultCode == RESULT_OK;
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
        if (prefs.getBoolean(Constants.PREF_CAPTURE_SCREEN_ENABLED, false) != allowCapture) {
            SharedPreferences.Editor editor1 = prefs.edit();
            editor1.putBoolean(Constants.PREF_CAPTURE_SCREEN_ENABLED, allowCapture);
            editor1.apply();
        }

        if (resultCode == RESULT_OK) {
            MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            MediaProjection projection = projectionManager.getMediaProjection(RESULT_OK, data);

            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);

            Point size = new Point();
            getWindowManager().getDefaultDisplay().getSize(size);

            if (mCapturer == null) {
                mCapturer = new ScreenCapturer(projection, size.x, size.y, metrics.densityDpi);
            }
        }
    } else if (requestCode == Constants.REQUEST_VALIDATE) {
        if (resultCode == Activity.RESULT_CANCELED) {
            UiUtil.showButtonDialog(this, null,
                    getString(R.string.prefsDisabledMissingPermissions),
                    android.R.string.ok, (dialogInterface, i) -> onStart(), -1, null);
        } else {
            onStart();
        }
    }
}
 
Example #16
Source File: ScreenRecordByCodecActivity.java    From ScreenCapture with MIT License 5 votes vote down vote up
private ScreenRecorder newRecorder(MediaProjection mediaProjection, VideoEncodeConfig video,
                                       AudioEncodeConfig audio, File output) {
        final VirtualDisplay display = getOrCreateVirtualDisplay(mediaProjection, video);
        ScreenRecorder r = new ScreenRecorder(video, audio, display, output.getAbsolutePath());
        r.setCallback(new ScreenRecorder.Callback() {
            long startTime = 0;

            @Override
            public void onStop(Throwable error) {
                runOnUiThread(() -> stopRecorder());
                if (error != null) {
                    toast("Recorder error ! See logcat for more details");
                    error.printStackTrace();
                    output.delete();
                } else {
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                            .addCategory(Intent.CATEGORY_DEFAULT)
                            .setData(Uri.fromFile(output));
                    sendBroadcast(intent);
                }
            }

            @Override
            public void onStart() {
//                mNotifications.recording(0);
            }

            @Override
            public void onRecording(long presentationTimeUs) {
                if (startTime <= 0) {
                    startTime = presentationTimeUs;
                }
                long time = (presentationTimeUs - startTime) / 1000;
//                mNotifications.recording(time);
            }
        });
        return r;
    }
 
Example #17
Source File: ImageScreenCast.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
ImageScreenCast(final Context context,
                final MediaProjection mediaProjection,
                final ImageReader imageReader,
                int width, int height) {
    super(context, mediaProjection, width, height);
    mImageReader = imageReader;
}
 
Example #18
Source File: ScreenRecordThread.java    From ScreenCapture with MIT License 5 votes vote down vote up
public ScreenRecordThread(int width, int height, int bitrate, int dpi, MediaProjection mp, String dstPath) {
    super(TAG);
    mWidth = width;
    mHeight = height;
    mBitRate = bitrate;
    mDpi = dpi;
    mMediaProjection = mp;
    mDstPath = dstPath;
}
 
Example #19
Source File: MediaProjectionHelper.java    From loco-answers with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Get media projection media projection.
 *
 * @param context the context
 * @return the media projection
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected static MediaProjection getMediaProjection(Context context){
    MediaProjectionManager mgr= (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    if(mMediaProjection!=null){
        mMediaProjection.stop();
        mMediaProjection=null;
    }
    mMediaProjection = mgr.getMediaProjection(Activity.RESULT_OK, (Intent) screenshotPermission.clone());
    return mMediaProjection;
}
 
Example #20
Source File: DisplayManager.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
/** @hide */
public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
        @NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
        int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
        @Nullable String uniqueId) {
    return mGlobal.createVirtualDisplay(mContext, projection,
            name, width, height, densityDpi, surface, flags, callback, handler, uniqueId);
}
 
Example #21
Source File: ScreenCast.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
public ScreenCast(Context context, MediaProjection mediaProjection, VideoQuality videoQuality) {
    mContext = context;
    mMediaProjection = mediaProjection;
    mVideoQuality = videoQuality;

    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    mDisplayDensityDpi = metrics.densityDpi;
}
 
Example #22
Source File: WebRTCEngine.java    From webrtc_android with MIT License 5 votes vote down vote up
@TargetApi(21)
private VideoCapturer createScreenCapturer() {
    if (mediaProjectionPermissionResultCode != Activity.RESULT_OK) {
        return null;
    }
    return new ScreenCapturerAndroid(
            mediaProjectionPermissionResultData, new MediaProjection.Callback() {
        @Override
        public void onStop() {
            Log.e(TAG, "User revoked permission to capture the screen.");
        }
    });
}
 
Example #23
Source File: ScreenRecorder.java    From SoloPi with Apache License 2.0 5 votes vote down vote up
/**
 * @param dpi for {@link VirtualDisplay}
 */
public ScreenRecorder(VideoEncodeConfig video, int dpi, MediaProjection mp,
                      String dstPath) {
    mWidth = video.width;
    mHeight = video.height;
    mDpi = dpi;
    mMediaProjection = mp;
    mDstPath = dstPath;
    mVideoEncoder = new VideoEncoder(video);

}
 
Example #24
Source File: ScreenCastVideoEncoder.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
private void requestMediaProjection() throws IOException {
    CountDownLatch latch = new CountDownLatch(1);

    Intent intent = new Intent();
    intent.setClass(mContext, MediaProjectionActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra("callback", new ResultReceiver(mCallbackHandler) {
        @Override
        protected void onReceiveResult(final int resultCode, final Bundle resultData) {
            if (resultCode == Activity.RESULT_OK) {
                Intent data = resultData.getParcelable("result");
                if (data != null) {
                    mMediaProjection = mMediaProjectionMgr.getMediaProjection(resultCode, data);
                    mMediaProjection.registerCallback(new MediaProjection.Callback() {
                        @Override
                        public void onStop() {
                            clean();
                        }
                    }, new Handler(Looper.getMainLooper()));
                }
            }
            latch.countDown();
        }
    });
    mContext.startActivity(intent);

    try {
        latch.await(30, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        throw new IOException();
    }
}
 
Example #25
Source File: SimpleRecordService.java    From SoloPi with Apache License 2.0 5 votes vote down vote up
private ScreenRecorder createRecorder(MediaProjection mediaProjection, final VideoEncodeConfig video
        , final File output) {
    ScreenRecorder r = new ScreenRecorder(video,
            1, mediaProjection, output.getAbsolutePath());
    r.setCallback(new ScreenRecorder.Callback() {
        long startTime = 0;
        @Override
        public void onStop(Throwable error) {
            isRecording = false;
        }

        @Override
        public void onStart() {
            lastRecorderStartTime = System.currentTimeMillis();
            LogUtil.e("yuawen", "录屏开始时间:" + lastRecorderStartTime);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    isRecording = true;
                    mNotifications.recording(0);
                }
            });
        }

        @Override
        public void onRecording(long presentationTimeUs) {
            if (startTime <= 0) {
                startTime = presentationTimeUs;
            }
            long time = (presentationTimeUs - startTime) / 1000;
            mNotifications.recording(time);
        }
    });
    return r;
}
 
Example #26
Source File: MediaReader.java    From AndroidScreenShare with Apache License 2.0 5 votes vote down vote up
public MediaReader(int width, int height,int videoBitrate, int videoFrameRate,
                   EncoderListener encoderListener, MediaProjection mp) {
    super(width, height, videoBitrate, videoFrameRate, encoderListener);
    mMediaProjection = mp;

    this.mWidth=width;
    this.mHeight=height;

    this.videoBitrate=videoBitrate;
    this.videoFrameRate=videoFrameRate;

    initVirtualDisplay();

}
 
Example #27
Source File: MediaScreenEncoder.java    From ScreenRecordingSample with Apache License 2.0 5 votes vote down vote up
public MediaScreenEncoder(final MediaMuxerWrapper muxer, final MediaEncoderListener listener,
	final MediaProjection projection, final int width, final int height, final int density,
	final int _bitrate, final int _fps) {

	super(muxer, listener, width, height);
	mMediaProjection = projection;
	mDensity = density;
	fps = (_fps > 0 && _fps <= 30) ? _fps : FRAME_RATE;
	bitrate = (_bitrate > 0) ? _bitrate : calcBitRate(_fps);
	final HandlerThread thread = new HandlerThread(TAG);
	thread.start();
	mHandler = new Handler(thread.getLooper());
}
 
Example #28
Source File: ScreenCastManager.java    From DeviceConnect-Android with MIT License 4 votes vote down vote up
/**
 * MediaProjection のパーミッションの許可を要求します.
 *
 * @param callback 許可の結果を通知するコールバック
 */
synchronized void requestPermission(final PermissionCallback callback) {
    if (mMediaProjection != null) {
        callback.onAllowed();
        return;
    }

    Intent intent = new Intent();
    intent.setClass(mContext, PermissionReceiverActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(PermissionReceiverActivity.EXTRA_CALLBACK, new ResultReceiver(mCallbackHandler) {
        @Override
        protected void onReceiveResult(final int resultCode, final Bundle resultData) {
            if (resultCode == Activity.RESULT_OK) {
                Intent data = resultData.getParcelable(PermissionReceiverActivity.RESULT_DATA);
                if (data != null) {
                    mMediaProjection = mMediaProjectionMgr.getMediaProjection(resultCode, data);
                    mMediaProjection.registerCallback(new MediaProjection.Callback() {
                        @Override
                        public void onStop() {
                            clean();
                        }
                    }, new Handler(Looper.getMainLooper()));
                }
            }

            if (mMediaProjection != null) {
                callback.onAllowed();
            } else {
                callback.onDisallowed();
            }
        }
    });

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
        mContext.startActivity(intent);
    } else {
        // Android 10(Q) からは、バックグラウンドから Activity を起動できなくなったので、
        // Notification から起動するようにします。
        NotificationUtils.createNotificationChannel(mContext);
        NotificationUtils.notify(mContext, NOTIFICATION_ID, 0, intent,
                mContext.getString(R.string.host_notification_projection_warnning));
    }
}
 
Example #29
Source File: SurfaceScreenCast.java    From DeviceConnect-Android with MIT License 4 votes vote down vote up
public SurfaceScreenCast(Context context, MediaProjection mediaProjection, Surface surface, VideoQuality videoQuality) {
    super(context, mediaProjection, videoQuality);
    mOutputSurface = surface;
}
 
Example #30
Source File: TelescopeLayout.java    From telescope with Apache License 2.0 4 votes vote down vote up
@TargetApi(LOLLIPOP) void captureNativeScreenshot(final MediaProjection projection) {
  capturingStart();

  // Wait for the next frame to be sure our progress bars are hidden.
  post(() -> {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
    final int width = displayMetrics.widthPixels;
    final int height = displayMetrics.heightPixels;

    @SuppressLint("WrongConstant")
    ImageReader imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
    Surface surface = imageReader.getSurface();

    final VirtualDisplay display =
        projection.createVirtualDisplay("telescope", width, height, displayMetrics.densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, surface, null, null);

    imageReader.setOnImageAvailableListener(reader -> {
      Image image = null;
      Bitmap bitmap = null;

      try {
        image = reader.acquireLatestImage();

        post(this::capturingEnd);

        if (image == null) {
          return;
        }

        saving = true;

        Image.Plane[] planes = image.getPlanes();
        ByteBuffer buffer = planes[0].getBuffer();
        int pixelStride = planes[0].getPixelStride();
        int rowStride = planes[0].getRowStride();
        int rowPadding = rowStride - pixelStride * width;

        bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height,
            Bitmap.Config.ARGB_8888);
        bitmap.copyPixelsFromBuffer(buffer);

        // Trim the screenshot to the correct size.
        final Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);

        checkLens();
        lens.onCapture(croppedBitmap,
            processed -> new SaveScreenshotTask(croppedBitmap).execute());
      } catch (UnsupportedOperationException e) {
        Log.e(TAG,
            "Failed to capture system screenshot. Setting the screenshot mode to CANVAS.", e);
        setScreenshotMode(ScreenshotMode.CANVAS);
        post(this::captureCanvasScreenshot);
      } finally {
        if (bitmap != null) {
          bitmap.recycle();
        }

        if (image != null) {
          image.close();
        }

        reader.close();
        display.release();
        projection.stop();
      }
    }, getBackgroundHandler());
  });
}