需求:后台周期性截屏
参考:https://www.jianshu.com/p/8d2302913960
重点:
1、ImageReader.newInstance中参数maxImages如果设置为1,则有时会取不到数据,原因不详。具体什么值合适,本人未详细测试,随意改成3
2、mImageReader.acquireLatestImage取相之前,先sleep(200),据说 mImageReader初始化需要时间。
3、只有Android 5.0到8.0才可用
代码:
private void initcaptureScreen(){
Thread captureScreen = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
requestScreenShot();
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
captureScreen.start();
}
public void requestScreenShot() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mMediaProjectionManager = (MediaProjectionManager) this.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
try {
if(LocalData!=null){
doScreen(1,null);
}else {
startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}
}catch (Exception ex){
Log.d(TAG,ex.getMessage());
}
}
else
{
Environment.toast(this, "系统版本过低,无法使用截屏功能。");
}
}
private Intent LocalData=null;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_MEDIA_PROJECTION: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && resultCode == -1 && data != null) {
LocalData = data;
doScreen(0,LocalData);
}else{
}
}
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void doScreen(int mode,Intent localData){
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if(mode == 0) {
mMediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, LocalData);
}
}
mImageReader = ImageReader.newInstance(
getScreenWidth(),
getScreenHeight(),
PixelFormat.RGBA_8888,
3);
startScreenShot(mode);
}catch (Exception ex){
Log.d(TAG,"doScreen:"+ex.getMessage());
}
}
private int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
private int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void virtualDisplay() {
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
getScreenWidth(),
getScreenHeight(),
Resources.getSystem().getDisplayMetrics().densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(),null, null);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public void startScreenShot(int mode) {
virtualDisplay();
if(mode == 0) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
Image image = mImageReader.acquireLatestImage();
AsyncTaskCompat.executeParallel(new ScreenShotSaveTask(), image);
}
},
300);
}else{
try {
Thread.sleep(200);
Image image = mImageReader.acquireLatestImage();
if(image == null){
Log.d(TAG,"image is null");
}else {
AsyncTaskCompat.executeParallel(new ScreenShotSaveTask(), image);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private class ScreenShotSaveTask extends AsyncTask<Image, Void, String> {
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected String 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);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
image.close();
File fileImage = null;
if (bitmap != null) {
try {
fileImage = RemoteServerFileManager.getScreenShotFile();
if (!fileImage.exists()) {
fileImage.createNewFile();
}
FileOutputStream out = new FileOutputStream(fileImage);
bitmap.compress(Bitmap.CompressFormat.PNG, 40, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
fileImage = null;
} catch (IOException e) {
e.printStackTrace();
fileImage = null;
}
}
if (fileImage != null) {
return fileImage.getPath();
}
return null;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onPostExecute(String bitmapPath) {
super.onPostExecute(bitmapPath);
OnSavedFinish(bitmapPath);
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
mVirtualDisplay=null;
}
}
}
public void OnSavedFinish (String imagePath){
}
public static final int REQUEST_MEDIA_PROJECTION = 0x8000;
private MediaProjection mMediaProjection;
private ImageReader mImageReader;
private MediaProjectionManager mMediaProjectionManager;
private VirtualDisplay mVirtualDisplay;