How to Use Media Projection API for Screen Capture

In this article we are going to learn about Media projection API for Screen capture.

Introduction

Media Projection was introduced in Lollipop and gives us the ability to capture what’s on the screen and also recording screen.

Media Projection API was introduced in Android API level  21. Using this API we can capture  the screen.

Foreground permission is required for android 10 and above version but  foreground permissions are not required for versions below Android 10 without that we can record screen but for android 10 and above we want foreground permission Have to take it and show foreground notification with it, only then we will be able to record screen in device above Android 10.

Required Permissions For Screen Capture are given below:

  • Android SDK v21
  • <uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
  • <uses-permission android:name=”android.permission.RECORD_AUDIO”/>
  • <uses-permission android:name=”android.permission.FOREGROUND_SERVICE”/>

Setup Your Manifest File(for Android 10 and above version) :

<application
<service android:enabled="true"
android:name=".ScreenCapturerService"
android:foregroundServiceType="mediaProjection"> </service>
</application>

Steps For Capture Screen:

Step-1  Send request for permission

Launching this intent will show a  dialog to the user which allows them for screen capture.

MediaProjectionManager mProjectionManager (MediaProjectionManager)getSystemService(android.content.Context.MEDIA_PROJECTION_SERVICE);
Intent permissionIntent = mProjectionManager.createScreenCaptureIntent();
startActivityForResult(permissionIntent, REQUEST_CODE_CAPTURE_PERM);

When you send request you can show dialog like this given below:

Below Android 10 you can see like this dialog:

How to Use Media Projection API for Screen Capture_1

Above Android 10 you can See like this dialog:

How to Use Media Projection API for Screen Capture_2

Step-2 Get call back of request for permission

Once they accept, you can use the result code and data intent returned in onActivityResult, we are able to create a  Media Projection.

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (REQUEST_CODE_CAPTURE_PERM == requestCode) {
if (resultCode == RESULT_OK) {
//permission allow

} else {
//permission deny
}
}
}

Step-3 Create Media Projection and create notification

private MediaProjection getMediaProjection() {
   if (mediaProjection == null) {
       mediaProjection = ApplicationClass.mProjectionManager.getMediaProjection(mResultCode, mResultData);
   }
   return mediaProjection;
}

Step-4 Then we use Image Reader for  capture screen with defined the height and width using the Window’s DisplayMetrics so it exactly matched the screen size. and define the path where you want to save your capture screen.Using this method you can capture the screen.

private MediaProjection mediaProjection;
ImageReader mImageReader;
String image_ss;
String ssImageFilePath;

public void captureImage() {
       if (mediaProjection == null) {
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//                showNotification();
               Toast.makeText(this, "Captured", Toast.LENGTH_SHORT).show();
           } else {
               startForeground(1, new Notification());
           }
       }
       WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
       Display display = wm.getDefaultDisplay();
       final DisplayMetrics metrics = new DisplayMetrics();
       display.getMetrics(metrics);
       Point size = new Point();
       display.getRealSize(size);
       int mWidth = size.x;
       int mHeight = size.y;
       int mDensity = metrics.densityDpi;
       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;
       if (getMediaProjection() != null) {
           getMediaProjection().createVirtualDisplay("ScreenShot", mWidth, mHeight, mDensity, flags, mImageReader.getSurface(), null, handler);
       }
       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();
               FileOutputStream bytes = null;
               File capturedImages = new File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES).getAbsolutePath() + "/Screen Recorder");
               if (!capturedImages.exists()) {
                   capturedImages.mkdirs();
               }
               image_ss = "Screen_Recording_Image_" + System.currentTimeMillis();
               ssImageFilePath = capturedImages + File.separator + image_ss + ".jpg";
               Log.d(TAG, ssImageFilePath);
               File f = null;
               try {
                   f = new File(ssImageFilePath);
                   bytes = new FileOutputStream(f);
                   realSizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
                   bytes.flush();
                   bytes.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               MediaScannerConnection.scanFile(getApplicationContext(), new String[]{ssImageFilePath}, null, new MediaScannerConnection.OnScanCompletedListener() {
                   public void onScanCompleted(String path, Uri uri) {
                       Intent intent1 = new Intent(getApplicationContext(), TransparentActivity.class).addFlags(FLAG_ACTIVITY_NEW_TASK);
                       intent1.putExtra("path", ssImageFilePath);
                       Log.i(TAG, "onActivityResult:Path--->" + ssImageFilePath);
                       startActivity(intent1);
                       Log.d(TAG, ssImageFilePath);
                       stopCapture();
                   }
               });
           }
       }, handler);
}

Stop Capture Screen method:

private void stopCapture() {
   if (mediaProjection != null) {
       mediaProjection.stop();
   }
   mediaProjection = null;
}

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories