适配了Android5.0以上的截图方法,实现了后台连续截图;使用该方法请求授权同意后开始截图:
private MediaProjectionManager mMediaProjectionManager;
public void getMediaProjectionManger() {
mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mMediaProjectionManager != null) {
startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), RECORD_REQUEST_CODE);
}
}
由于targetSdkVersion 29及以上要求getMediaProjection需要再前台服务执行,所以在onActivityResult里面启动服务:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
Intent intent = new Intent(ZkScreenshotActivity.this, ZkA5AboveScreenshotService.class);
intent.putExtra("code",resultCode);
intent.putExtra("data",data);
ZkUtlis.startService(ZkScreenshotActivity.this,intent);
}
}
Service方法如下:
public class ZkA5AboveScreenshotService extends Service {
private String mTag = "ZkA5AboveScreenshotService";
private int mResultCode;
private Intent mResultData;
private MediaProjection mMediaProjection;
private MediaProjectionManager mMediaProjectionManager;
private int mWidth;
private int mHeight;
private int mDensity;
private ImageReader mImageReader;
private int mImagesProduced;
private int mCount = 0;
@Override
public void onCreate() {
super.onCreate();
mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
createNotificationChannel();
mResultCode = intent.getIntExtra("code", -1);
mResultData = intent.getParcelableExtra("data");
mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, Objects.requireNonNull(mResultData));
Log.d(mTag, "mMediaProjection created: " + mMediaProjection);
startCaptureReader();
return super.onStartCommand(intent, flags, startId);
}
/**
* startCaptureReader
*/
@SuppressLint("WrongConstant")
private void startCaptureReader() {
WindowManager wm = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
mWidth = size.x;
mHeight = size.y;
Log.d(mTag,"width:" + mWidth + " height:" + mHeight);
DisplayMetrics metrics = getResources().getDisplayMetrics();
mDensity = metrics.densityDpi;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, 0x01, 2);
mMediaProjection.createVirtualDisplay("screencap", mWidth, mHeight, mDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), null);
}
/**
* ImageAvailableListener
*/
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
@Override
public void onImageAvailable(ImageReader reader) {
try (Image image = reader.acquireLatestImage()) {
if (image != null) {
/**
* 截图结果,会在内容更新自动回调,该方法可以实现连续截图,无需重复启用截图方法
*/
}
image.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Create Notification Channel
*/
private void createNotificationChannel() {
//获取一个Notification构造器
Notification.Builder builder = new Notification.Builder(this.getApplicationContext());
//点击后跳转的界面,可以设置跳转数据
Intent nfIntent = new Intent(this, ZkScreenshotActivity.class);
// 设置PendingIntent
builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
// 设置下拉列表中的图标(大图标)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher))
// 设置下拉列表里的标题
//.setContentTitle("SMI InstantView")
// 设置状态栏内的小图标
.setSmallIcon(R.mipmap.ic_launcher)
// 设置上下文内容
.setContentText("is running......")
// 设置该通知发生的时间
.setWhen(System.currentTimeMillis());
/*以下是对Android 8.0的适配*/
//普通notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId("notification_id");
}
//前台服务notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("notification_id", "notification_name", NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(channel);
}
// 获取构建好的Notification
Notification notification = builder.build();
//设置为默认的声音
notification.defaults = Notification.DEFAULT_SOUND;
startForeground(110, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(mTag, "Service onDestroy");
if (mImageReader != null) {
mImageReader.setOnImageAvailableListener(null,null);
mImageReader.close();
mImageReader = null;
}
if (mMediaProjection != null) {
mMediaProjection.stop();
mMediaProjection = null;
}
mMediaProjectionManager = null;
}
下面是将Image转Bitmap
/**
* Image 转 Bitmap
* @param image
*/
private Bitmap imageToBitmap(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
Bitmap bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
return bitmap;
}