1.正常截屏
1.获取intent,startActivity()
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
2.回调并开始截图
@Override
protected 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() {
@Override
public 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(){
@Override
public void onImageAvailable(ImageReader reader) {
handler.removeMessages(0);
Log.e(Tag,"startScreenShot----,onImageAvailable----");
mImageReader.setOnImageAvailableListener(null,null);
new CreateBitmapTask().execute();
}
},handler);
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.e(Tag,"startScreenShot----,handler.postDelayed----");
mImageReader.setOnImageAvailableListener(null,null);
new CreateBitmapTask().execute();
}
}, 700);
}
public class CreateBitmapTask extends AsyncTask<Image, Void, Bitmap> {
@Override
protected 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;
}
@Override
protected 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.获取 intent
private 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() {
@Override
public void onFinish(Bitmap bitmap) {
WindowUiManager.setScreenImageBitmap(bitmap);
LogUtil.e("截屏完成,用时time: " + (System.currentTimeMillis() - takeScreenTime));
}
});
screenShotHelper.startScreenShot();