Android realizes screen capture function
- 2021-12-13 16:50:42
- OfStack
Introduction
At present, there are many methods of screen capture, root is not applicable, or other methods are limited, and the official scheme is the best-MediaProjection
Introduction
After Android 5.0, the open recording screen API takes one frame of data in the video, so that screen capture can be realized
Steps
Authorize in activity, initialize and take screenshots in service, of course, you can take screenshots in the background, but bug with memory overflow in 6.0 system
1:build.gradle
compileSdkVersion 21
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.aile.screenshot"
multiDexEnabled true
minSdkVersion 21
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
2: Licensing in activity
public void requestCapturePermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}
@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) {
Service.setResultData(data);
startService(new Intent(this, Service.class));
finish();
}
break;
}
}
3: Initialize ImageReader, MediaProjection in service
private void createImageReader() {
mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
}
public void setUpMediaProjection() {
mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
}
}
4: Important steps to complete screenshots in service:
private void startScreenShot() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
startVirtual();
}
}, 0);
handler.postDelayed(new Runnable() {
@Override
public void run() {
startCapture();
}
}, 50);
}
public void startVirtual() {
if (mMediaProjection != null) {
virtualDisplay();
} else {
setUpMediaProjection();
virtualDisplay();
}
}
private void virtualDisplay() {
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
// The core of exception handling
private void startCapture() {
Image image = null;
try {
image = mImageReader.acquireLatestImage();
} catch (IllegalStateException e) {
if (null != image) {
image.close();
image = null;
image = mImageReader.acquireLatestImage();
}
}
if (image == null) {
startScreenShot();
} else {
SaveTask mSaveTask = new SaveTask();
AsyncTaskCompat.executeParallel(mSaveTask, image);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
stopVirtual();
tearDownMediaProjection();
}
}, 0);
}
}
public class SaveTask extends AsyncTask<Image, Void, Bitmap> {
@Override
protected Bitmap doInBackground(Image... params) {
if (params == null || params.length < 1 || params[0] == null) {
return null;
}
Image image = params[0];
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].getRowStride();
int rowPadding = rowStride - pixelStride * width;
Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
// This is the initial screenshot
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
image.close();
return bitmap;
}
@Override
protected void onPostExecute(final Bitmap bitmap) {
super.onPostExecute(bitmap);
// Deal with bitmap Business code of
}
5: Bitmap to IS stream, screenshot of designated area
// Will Bitmap Convert to InputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
// Screenshot of designated area
Rect mRect = new Rect(51, 74, 58, 62);
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, true);
Bitmap bm = bitmapRegionDecoder.decodeRegion(mRect, null);
6: Handling of Timed Tasks
private Timer timer = new Timer();
public void shootByTime() {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
startScreenShot();
super.handleMessage(msg);
}
};
timer.schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}, 0, 100);
}
7: Handling of horizontal and vertical screens
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_PORTRAIT) {
mRect = new Rect(51, 775, 745, 47);
} else if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_LANDSCAPE) {
mRect = new Rect(54, 24, 545, 45);
}
}
8: There are still many, just go according to the needs of OK, there is no difficult thing, need to keep learning and accumulating