1.正常截屏
1.获取intent,startActivity()MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);2.回调并开始截图@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_MEDIA_PROJECTION) {if (resultCode == RESULT_OK && data != null) {ScreenShotHelper screenShotHelper = new ScreenShotHelper(AiActivity.this, resultCode, fxIntent, new ScreenShotHelper.OnScreenShotListener() {@Overridepublic void onFinish(Bitmap bitmap) {WindowUiManager.setScreenImageBitmap(bitmap);LogUtil.e("截屏完成,用时time: " + (System.currentTimeMillis() - takeScreenTime));}});screenShotHelper.startScreenShot();}}}
package com.alpha.aiservice.utils;import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;public class ScreenShotHelper {private String Tag = this.getClass().getSimpleName();public interface OnScreenShotListener {void onFinish(Bitmap bitmap);}private OnScreenShotListener mOnScreenShotListener;private ImageReader mImageReader;private MediaProjection mMediaProjection;private VirtualDisplay mVirtualDisplay;private final SoftReference<Context> mRefContext;public ScreenShotHelper(Context context, int resultCode, Intent data, OnScreenShotListener onScreenShotListener) {this.mOnScreenShotListener = onScreenShotListener;this.mRefContext = new SoftReference<Context>(context);mMediaProjection = getMediaProjectionManager().getMediaProjection(resultCode, data);mImageReader = ImageReader.newInstance(getScreenWidth(), getScreenHeight(), PixelFormat.RGBA_8888, 1);}public void startScreenShot() {createVirtualDisplay();Handler handler = new Handler();mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener(){@Overridepublic void onImageAvailable(ImageReader reader) {handler.removeMessages(0);Log.e(Tag,"startScreenShot----,onImageAvailable----");mImageReader.setOnImageAvailableListener(null,null);new CreateBitmapTask().execute();}},handler);handler.postDelayed(new Runnable() {@Overridepublic void run() {Log.e(Tag,"startScreenShot----,handler.postDelayed----");mImageReader.setOnImageAvailableListener(null,null);new CreateBitmapTask().execute();}}, 700);}public class CreateBitmapTask extends AsyncTask<Image, Void, Bitmap> {@Overrideprotected Bitmap doInBackground(Image... params) {Image image = mImageReader.acquireLatestImage();Log.e(Tag,"startScreenShot----,onImageAvailable----doInBackground");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);bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);image.close();return bitmap;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);mVirtualDisplay.release();mMediaProjection.stop();if (mOnScreenShotListener != null) {mOnScreenShotListener.onFinish(bitmap);}}}private MediaProjectionManager getMediaProjectionManager() {return (MediaProjectionManager) getContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);}private void createVirtualDisplay() {mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",getScreenWidth(),getScreenHeight(),Resources.getSystem().getDisplayMetrics().densityDpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mImageReader.getSurface(),null,null);}private Context getContext() {return mRefContext.get();}public static int getScreenWidth() {return Resources.getSystem().getDisplayMetrics().widthPixels;}public static int getScreenHeight() {return Resources.getSystem().getDisplayMetrics().heightPixels;}
}
2.反射截屏
1.获取 intentprivate Intent getMediaProjectionIntentWithoutPermission(Context context) {String mPackageName = context.getPackageName();int mUid = -1;PackageManager packageManager = context.getPackageManager();ApplicationInfo aInfo;try {aInfo = packageManager.getApplicationInfo(mPackageName, 0);mUid = aInfo.uid;} catch (PackageManager.NameNotFoundException e) {Log.e(TAG, "unable to look up package name", e);}Log.i(TAG, "requestPermissions mPackageName " + mPackageName + ", mUid " + mUid);try {Class<?> serviceManager = Class.forName("android.os.ServiceManager");IBinder serviceBinder = (IBinder) serviceManager.getMethod("getService", String.class).invoke(serviceManager, "media_projection");Class<?> stub = Class.forName("android.media.projection.IMediaProjectionManager$Stub");Object projectionManagerService = stub.getMethod("asInterface", IBinder.class).invoke(stub, serviceBinder);Method hasProjectionPermission = projectionManagerService.getClass().getMethod("hasProjectionPermission", int.class, String.class);boolean result = (boolean) hasProjectionPermission.invoke(projectionManagerService, mUid, mPackageName);Log.i(TAG, "hasProjectionPermission " + result);Method createProjection = projectionManagerService.getClass().getMethod("createProjection", int.class, String.class, int.class, boolean.class);Class<?> projectionClass = Class.forName("android.media.projection.IMediaProjection");Method asBinderMethod = projectionClass.getMethod("asBinder");Object projectionObj = createProjection.invoke(projectionManagerService, mUid, mPackageName, 0, true);IBinder projectionBinder = (IBinder) asBinderMethod.invoke(projectionObj);Intent intent = new Intent();Method putBinderExtra = intent.getClass().getMethod("putExtra", String.class, IBinder.class);putBinderExtra.invoke(intent, "android.media.projection.extra.EXTRA_MEDIA_PROJECTION", projectionBinder);Log.i(TAG, "successfully get media projection intent");return intent;} catch (ClassNotFoundException | ClassCastException | NoSuchMethodException | SecurityException| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {Log.w(TAG, "创建 Intent 失败,"+e.toString());e.printStackTrace();return null;}}2.拿到反射后intent,开始截屏Intent fxIntent = getMediaProjectionIntentWithoutPermission(this);ScreenShotHelper screenShotHelper = new ScreenShotHelper(AiActivity.this, RESULT_OK, fxIntent, new ScreenShotHelper.OnScreenShotListener() {@Overridepublic void onFinish(Bitmap bitmap) {WindowUiManager.setScreenImageBitmap(bitmap);LogUtil.e("截屏完成,用时time: " + (System.currentTimeMillis() - takeScreenTime));}});screenShotHelper.startScreenShot();