Android implements the rectangular area screenshot method and android screenshot

Source: Internet
Author: User

Android implements the rectangular area screenshot method and android screenshot

There are two ways to take screenshots and crop the screenshots: early and late. Early is to take a full screen first, and then let the user modify the captured image. In contrast, late is to let the user draw a area on the screen before and crop. In fact, there is no big difference between the two. This article will talk about how to implement it later.

It can be divided into three steps later:

1. rectangular area marked on the screen

2. Call the system interface screenshot

3. Crop

As follows:

Step 1: Mark the area on the screen

First, determine the features required to identify the region:

1. Drag your fingers to form a rectangular area;

2. You can move the area of the selected rectangle;

3. You can drag the border of the rectangular area to adjust the size;

4. After the selection is complete, the "Confirm" and "cancel" functions are available. When "Confirm", you can obtain the selected region location. Note that the button position should be adaptive. For example, if the selection box occupies almost full screen, the button should be placed inside the selection box.

The simplest way is to write a custom View and execute different functions based on the touch location. The implementation is very simple, as long as you carefully put each status on the line, the code please see Bigbang project MarkSizeView class.

Step 2: Call the system interface screenshot

Screenshots must be taken in the Activity because startActivityForResult () needs to be called (). However, you can also upload the mMediaProjectionManager to the service for subsequent processing.

It should also be noted that the Activity itself should be transparent during screenshot capture, and it cannot affect the content to be captured.

View the Code directly:

Public class ScreenCaptureActivity extends Activity {private static final String TAG = ScreenCaptureActivity. class. getName (); private MediaProjectionManager injection; private int REQUEST_MEDIA_PROJECTION = 1; private SimpleDateFormat dateFormat; private String pathImage; private WindowManager mWindowManager; private ImageReader mImageReader; private MediaProjection mMediaProjection; Private int mResultCode; private Intent mResultData; private VirtualDisplay mVirtualDisplay; private String strDate; private int running wwidth; private int running wheight; private String nameImage; private int mScreenDensity; @ RequiresApi (api = Build. VERSION_CODES.LOLLIPOP) @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); mMediaProjectionManager = (Me DiaProjectionManager) getApplication (). getSystemService (Context. MEDIA_PROJECTION_SERVICE); createVirtualEnvironment (); startActivityForResult (mMediaProjectionManager. createScreenCaptureIntent (), REQUEST_MEDIA_PROJECTION) ;}@ TargetApi (Build. VERSION_CODES.LOLLIPOP) @ Override public void onActivityResult (int requestCode, int resultCode, Intent data) {if (requestCode = REQUEST_MEDIA_PROJECTION) {I F (resultCode! = Activity. RESULT_ OK) {return;} else if (data! = Null & resultCode! = 0) {mResultCode = resultCode; mResultData = data; startVirtual (); new Handler (loler. getMainLooper ()). postDelayed (new Runnable () {@ Override public void run () {startCapture () ;}, 100) ;}}@ RequiresApi (api = Build. VERSION_CODES.KITKAT) private void createVirtualEnvironment () {dateFormat = new SimpleDateFormat ("yyyy_MM_dd_hh_mm_ss"); strDate = dateFormat. format (new Date (); pathImage = Envir Onment. getExternalStorageDirectory (). getPath () + "/Pictures/"; nameImage = pathImage + strDate + ". png "; mMediaProjectionManager = (MediaProjectionManager) getApplication (). getSystemService (Context. MEDIA_PROJECTION_SERVICE); mWindowManager = (WindowManager) getApplication (). getSystemService (Context. WINDOW_SERVICE); required wwidth = mWindowManager. getdefadisplay display (). getWidth (); fig = mWindow Manager. getdefadisplay display (). getHeight (); DisplayMetrics metrics = new DisplayMetrics (); mWindowManager. getdefadisplay display (). getMetrics (metrics); mScreenDensity = metrics. densityDpi; mImageReader = ImageReader. newInstance (required wwidth, required wheight, 0x1, 2); // ImageFormat. RGB_565 Log. I (TAG, "prepared the virtual environment") ;}@ TargetApi (Build. VERSION_CODES.LOLLIPOP) public void startVirtual () {if (MMediaProjection! = Null) {Log. I (TAG, "want to display virtual"); virtualDisplay ();} else {Log. I (TAG, "start screen capture intent"); Log. I (TAG, "want to build mediaprojection and display virtual"); setUpMediaProjection (); virtualDisplay () ;}@ TargetApi (Build. VERSION_CODES.LOLLIPOP) public void setUpMediaProjection () {mMediaProjection = mMediaProjectionManager. getMediaProjection (mResultCode, mResultData); Log. I (TAG, "mMediaProjection defined") ;}@ TargetApi (Build. VERSION_CODES.LOLLIPOP) private void virtualDisplay () {mVirtualDisplay = mMediaProjection. createVirtualDisplay ("screen-mirror", interval wwidth, interval wheight, mScreenDensity, DisplayManager. VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader. getSurface (), null, null); Log. I (TAG, "virtual displayed") ;}@ TargetApi (Build. VERSION_CODES.LOLLIPOP) private Void startCapture () {strDate = dateFormat. format (new java. util. date (); nameImage = pathImage + strDate + ". png "; Image image = mImageReader. acquireLatestImage (); int width = image. getWidth (); int height = image. getHeight (); final Image. plane [] planes = image. getPlanes (); final ByteBuffer buffer = planes [0]. getBuffer (); int pixelStride = planes [0]. getPixelStride (); int rowStride = planes [0]. getRo WStride (); int rowPadding = rowStride-pixelStride * width; Bitmap bitmap = Bitmap. createBitmap (width + rowPadding/pixelStride, height, Bitmap. config. ARGB_8888); bitmap. copyPixelsFromBuffer (buffer); bitmap = Bitmap. createBitmap (bitmap, 0, 0, width, height); image. close (); Log. I (TAG, "image data captured"); // Save the screenshot result. if you want to crop the image, process bitmap if (bitmap! = Null) {try {File fileImage = new File (nameImage); if (! FileImage. exists () {fileImage. createNewFile (); Log. I (TAG, "image file created") ;}fileoutputstream out = new FileOutputStream (fileImage); if (out! = Null) {bitmap. compress (Bitmap. compressFormat.. PNG, 100, out); out. flush (); out. close (); Intent media = new Intent (Intent. ACTION_MEDIA_SCANNER_SCAN_FILE); Uri contentUri = Uri. fromFile (fileImage); media. setData (contentUri); this. sendBroadcast (media); Log. I (TAG, "screen image saved") ;}} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace () ;}}@ Ta RgetApi (Build. VERSION_CODES.LOLLIPOP) private void tearDownMediaProjection () {if (mMediaProjection! = Null) {mMediaProjection. stop (); mMediaProjection = null;} Log. I (TAG, "mMediaProjection undefined ");}}

Step 3: Crop

Crop the screenshot result bitmap in step 2 based on the region mRect obtained in Step 1:

if (mRect != null) { if (mRect.left < 0) mRect.left = 0; if (mRect.right < 0) mRect.right = 0; if (mRect.top < 0) mRect.top = 0; if (mRect.bottom < 0) mRect.bottom = 0; int cut_width = Math.abs(mRect.left - mRect.right); int cut_height = Math.abs(mRect.top - mRect.bottom); if (cut_width > 0 && cut_height > 0) { Bitmap cutBitmap = Bitmap.createBitmap(bitmap, mRect.left, mRect.top, cut_width, cut_height);}

Note that when calling the system screenshot function, if the mobile phone has a NavigationBar (Virtual navigation bar), The windowHeight value does not include the height of the NavigationBar. If no adjustment is made, the screenshot is compressed. For details about how to obtain the actual height of the screen, refer to how Android determines whether the NavigationBar is displayed (obtain the actual height of the screen ).

In addition, the NavigationBar will also cause the screenshot result to show a border. The border color is transparent, because the rowPadding in the second step of code! = 0. screenshots are shown in:

If we want to save or crop the result, we must remove the border to find the real content area, that is, the content between the first opaque pixel and the last opaque pixel can then be cropped in step 3. The Code is as follows:

int[] pixel=new int[width];bitmap.getPixels(pixel,0,width ,0,0,width,1);int leftPadding=0;int rightPadding=width;for (int i=0;i<pixel.length;i++){ if (pixel[i]!=0){ leftPadding=i; break; }}for (int i=pixel.length-1;i>=0;i--){ if (pixel[i]!=0){ rightPadding=i; break; }}bitmap=Bitmap.createBitmap(bitmap,leftPadding, 0, rightPadding-leftPadding, height);

The processing result is as follows:

You may think it's rowPadding! = 0: The border appears, and the border is only on the right. Why not cut off the rowPadding width on the right? In fact, the above method is used only because the box is also generated on the left side without adjusting the previous wheight.

For the complete code, see the MarkSizeView class, ScreenCaptureActivity class, And ScreenCapture class of the Bigbang project.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.