8月份的blog:记录一下工作中的经历。
官网:https://developer.android.com/reference/android/media/ImageReader.html
ImageReader可以直接获取屏幕渲染数据,得到屏幕数据后自己想干嘛就干嘛。得到的数据是image格式,这个数据从系统内核分发到我们get到,平均延迟是30ms。如下图。
ImageReader给出的image数据是根据我们的需求,也就是你能处理多少,系统就会给多少,imagereader给出的数据最快有5ms延迟,以系统60帧为例,16ms为一帧,有时候会随机等待一帧,也就是5+16=21ms左右。
1.相关变量:
private static final String TAG = MainActivity.class.getName();
private static final int REQUEST_CODE = 100;
public MediaProjectionManager mProjectionManager;
private static int IMAGES_PRODUCED;
private static final String SCREENCAP_NAME = "screencap";
private MediaProjection mMediaProjection;
private ImageReader mImageReader;
private VirtualDisplay mVirtualDisplay;
private int mDensity;
private int mWidth;
private int mHeight;
2.利用mediaprojection发起请求
public void getMediaProjectionManger() {
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mProjectionManager != null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
}
}
3.在回调中创建ImageReader
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
DisplayMetrics metrics = getResources().getDisplayMetrics();
mDensity = metrics.densityDpi;
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(TAG,"width:"+mWidth+" height:"+mHeight);
// start capture reader
//mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGB_8888, 2);
mImageReader = ImageReader.newInstance(mWidth, mHeight, 0x01, 2);
//mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, null);
mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), null);
}
}
4.获取image数据
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
@Override
public void onImageAvailable(ImageReader reader) {
try (Image image = reader.acquireLatestImage()) {
if (image != null) {
String name = String.valueOf(System.currentTimeMillis());
IMAGES_PRODUCED++;
Log.e("captured image: ", String.valueOf(IMAGES_PRODUCED));
if (IMAGES_PRODUCED%10 == 0){
saveJpeg(image,name);
}
image.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.保存image数据
private void saveJpeg(Image image,String name) {
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);
//bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
ImageSaveUtil.saveBitmap2file(bitmap,getApplicationContext(),name);
}
ImageReader最好在前台服务中使用。