Android关于MediaProject截图的正确姿势(最新)
Posted 写Bug的渣渣高
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android关于MediaProject截图的正确姿势(最新)相关的知识,希望对你有一定的参考价值。
在使用 MediaProject 的过程种,遇到了N种错误,自己一直也没有解决
下面来分享一个我找到的资料,我对作者的代码进行了小部分的修改来完成我的功能。在这里非常感谢作者,
我在各种平台都搜集了很久,没有找到一个可用的 MeidaPorject 截屏代码,而网上的教程各式各样,但是实操都会遇到各种各样的问题。由于作者好像在除了 github 平台发布了代码之外,在其他平台并没有找到。
特此,使用了作者代码截屏的部分,并修改了部分代码,作者的github仓库
sdk 28
MainActivity
public class MainActivity extends BaseActivity implements View.OnClickListener
private static final int REQUEST_CODE = 100;
private static MediaProjection sMediaProjection;
Button mBtnCapture;
private MediaProjectionManager mProjectionManager;
private ScreenCapturer mSC;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnCapture = findViewById(R.id.btn_capture);
mBtnCapture.setOnClickListener(this);
mProjectionManager = (MediaProjectionManager) getSystemService(
Context.MEDIA_PROJECTION_SERVICE);
@Override
protected void onResume()
super.onResume();
@Override
public void onClick(View v)
switch (v.getId())
case R.id.btn_capture:
startActivityForResult(mProjectionManager.createScreenCaptureIntent(),
REQUEST_CODE);
break;
default:
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
Log.d("WOW", "on result : requestCode = " + requestCode + " resultCode = " + resultCode);
if (RESULT_OK == resultCode && REQUEST_CODE == requestCode)
sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
if (sMediaProjection != null)
Log.d("WOW", "Start capturing...");
new ScreenCapturer(this, sMediaProjection, "").startProjection();
BaseActivity
public class BaseActivity extends AppCompatActivity
private static final int REQUEST_CODE = 9527;
private static String[] PERMISSIONS =
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
;
@Override
protected void onResume()
super.onResume();
checkPermissions();
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (REQUEST_CODE == requestCode)
boolean isAllGranted = false;
for (int result : grantResults)
if (result != PackageManager.PERMISSION_GRANTED)
isAllGranted = false;
break;
isAllGranted = true;
if (!isAllGranted)
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Need Permission");
builder.setPositiveButton("Grant now", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
);
builder.setNegativeButton("Fuck yourself", null);
builder.show();
else
//permission
private void checkPermissions()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return;
Boolean isAllPermissionGranted = false;
for (String permission : PERMISSIONS)
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
isAllPermissionGranted = false;
break;
isAllPermissionGranted = true;
if (!isAllPermissionGranted)
requestPermissions(PERMISSIONS, REQUEST_CODE);
ScreenCapture
public class ScreenCapturer
private static MediaProjection sMediaProjection;
boolean isScreenCaptureStarted;
OnImageCaptureScreenListener listener;
private int mDensity;
private Display mDisplay;
private int mWidth;
private int mHeight;
private ImageReader mImageReader;
private VirtualDisplay mVirtualDisplay;
private Handler mHandler;
private String STORE_DIR;
private Context mContext;
public ScreenCapturer(Context context, MediaProjection mediaProjection, String savePath)
sMediaProjection = mediaProjection;
mContext = context;
isScreenCaptureStarted = false;
new Thread()
@Override
public void run()
Looper.prepare();
mHandler = new Handler();
Looper.loop();
.start();
if (TextUtils.isEmpty(savePath))
File externalFilesDir = mContext.getExternalFilesDir(null);
Log.d("WOW", "externalFilesDir:" + externalFilesDir.getAbsolutePath());
if (externalFilesDir != null)
STORE_DIR = externalFilesDir.getAbsolutePath() + "/myScreenshots";
else
Toast.makeText(mContext, "No save path assigned!", Toast.LENGTH_SHORT).show();
else
STORE_DIR = savePath;
public ScreenCapturer startProjection()
if (sMediaProjection != null)
File storeDir = new File(STORE_DIR);
if (!storeDir.exists())
boolean success = storeDir.mkdirs();
if (!success)
Log.d("WOW", "mkdir " + storeDir + " failed");
return this;
else
Log.d("WOW", "mkdir " + storeDir + " success");
else
Log.d("WOW", " " + storeDir + " exist");
else
Log.d("WOW", "get mediaprojection failed");
try
Thread.sleep(500); // 防止截屏截到 显示截屏权限的窗口
isScreenCaptureStarted = true;
catch (InterruptedException e)
e.printStackTrace();
WindowManager window = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = window.getDefaultDisplay();
final DisplayMetrics metrics = new DisplayMetrics();
// use getMetrics is 2030, use getRealMetrics is 2160, the diff is NavigationBar's height
mDisplay.getRealMetrics(metrics);
mDensity = metrics.densityDpi;
Log.d("WOW", "metrics.widthPixels is " + metrics.widthPixels);
Log.d("WOW", "metrics.heightPixels is " + metrics.heightPixels);
mWidth = metrics.widthPixels;
mHeight = metrics.heightPixels;
//start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = sMediaProjection.createVirtualDisplay(
"ScreenShot",
mWidth,
mHeight,
mDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
mImageReader.getSurface(),
null,
mHandler);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener()
@Override
public void onImageAvailable(ImageReader reader)
if (isScreenCaptureStarted)
Image image = null;
FileOutputStream fos = null;
Bitmap bitmap = null;
try
image = reader.acquireLatestImage();
if (image != null)
// bitmap = ImageUtils.image_ARGB8888_2_bitmap(metrics, image);
bitmap = ImageUtils.image_2_bitmap(image, Bitmap.Config.ARGB_8888);
if (null != listener)
listener.imageCaptured(ImageUtils.bitmap2byte(bitmap, 80));
Date currentDate = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyyMMddhhmmss");
String fileName = STORE_DIR + "/myScreen_" + date.format(
currentDate) + ".png";
fos = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
Log.d("WOW", "End now!!!!!! Screenshot saved in " + fileName);
Toast.makeText(mContext, "Screenshot saved in " + fileName,
Toast.LENGTH_LONG).show();
stopProjection();
catch (FileNotFoundException e)
e.printStackTrace();
finally
if (null != fos)
try
fos.close();
catch (IOException e)
e.printStackTrace();
if (null != bitmap)
bitmap.recycle();
if (null != image)
image.close();
, mHandler);
sMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);
return this;
public ScreenCapturer stopProjection()
isScreenCaptureStarted = false;
Log.d("WOW", "Screen captured");
mHandler.post(new Runnable()
@Override
public void run()
if (sMediaProjection != null)
sMediaProjection.stop();
);
return this;
public ScreenCapturer setListener(OnImageCaptureScreenListener listener)
this.listener = listener;
return this;
public interface OnImageCaptureScreenListener
public void imageCaptured(byte[] image);
private class MediaProjectionStopCallback extends MediaProjection.Callback
@Override
public void onStop()
mHandler.post(new Runnable()
@Override
public void run()
if (mVirtualDisplay != null)
mVirtualDisplay.release();
if (mImageReader != null)
mImageReader.setOnImageAvailableListener(null, null);
sMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
);
ImageUtils
public class ImageUtils
public static Bitmap image_ARGB8888_2_bitmap(DisplayMetrics metrics, Image image)
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int width = image.getWidth();
int height = image.getHeight();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * width;
int offset = 0;
Bitmap bitmap;
bitmap = Bitmap.createBitmap(metrics, width, height, Bitmap.Config.ARGB_8888);
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
int pixel = 0;
pixel |= (buffer.get(offset) & 0xff) << 16; // R
pixel |= (buffer.get(offset + 1) & 0xff) << 8; // G
pixel |= (buffer.get(offset + 2) & 0xff); // B
pixel |= (buf以上是关于Android关于MediaProject截图的正确姿势(最新)的主要内容,如果未能解决你的问题,请参考以下文章