-
Notifications
You must be signed in to change notification settings - Fork 0
Android 免Root截屏
ythy edited this page Nov 17, 2017
·
1 revision
- 用户访问许可, 需要在Activity进行
MediaProjectionManager mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
- 通过
onActivityResult()
回调, 启动截屏service
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
ScreenshotService.setResultData(data);
Intent intent = new Intent(getApplicationContext(), ScreenshotService.class);
intent.putExtra("position_x", getIntent().getIntExtra("position_x", 0));
intent.putExtra("position_y", getIntent().getIntExtra("position_y", 0));
startService(intent);
this.finish();
}
}
-
service
中取得手机测量信息
mMetrics = new DisplayMetrics();
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mWindowManager.getDefaultDisplay().getMetrics(mMetrics);
mScreenDensity = mMetrics.densityDpi;
mScreenWidth = mMetrics.widthPixels;
mScreenHeight = mMetrics.heightPixels;
- 创建
ImageReader
获取处理图片
mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
mImageReader.setOnImageAvailableListener(onImageAvailableListener, null);
- 设置
MediaProjection
启动截屏
private MediaProjectionManager getMediaProjectionManager() {
return (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
- 创建
VirtualDisplay
捕获截屏
mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME,
mScreenWidth, mScreenHeight, mScreenDensity,
VIRTUAL_DISPLAY_FLAGS,
mImageReader.getSurface(), null, null);
-
OnImageAvailableListener
监听函数中处理图片
@Override
public void onImageAvailable(ImageReader reader) {
Log.i(TAG, "in OnImageAvailable");
Image image = null;
FileOutputStream fos = null;
Bitmap bitmap = null;
try {
image = reader.acquireLatestImage();
if (image != null) {
Image.Plane[] planes = image.getPlanes();
if (planes[0].getBuffer() == null) {
return;
}
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.createBitmap(mMetrics, width, height, Bitmap.Config.ARGB_8888);
ByteBuffer buffer = planes[0].getBuffer();
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 |= (buffer.get(offset + 3) & 0xff) << 24; // A
bitmap.setPixel(j, i, pixel);
offset += pixelStride;
}
offset += rowPadding;
}
// write bitmap to a file
String fileName = FileUtil.getScreenShotsName(getApplicationContext());
fos = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
Toast.makeText(getApplicationContext(), "screenshot captured", Toast.LENGTH_SHORT).show();
CommonUtils.refreshMediaScanner(getApplicationContext(), new File(fileName));
onBack();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bitmap != null) {
bitmap.recycle();
}
if (image != null) {
image.close();
}
stopImageReader();
}
}
- 关闭各对象
private void stopMediaProjection() {
if (mMediaProjection != null) {
mMediaProjection.stop();
mMediaProjection = null;
}
}
private void stopVirtual() {
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
mVirtualDisplay = null;
}
}
private void stopImageReader(){
if(mImageReader != null){
mImageReader.setOnImageAvailableListener(null, null);
mImageReader.close();
}
}
- 模拟器不能正常截屏,图片是空白
- 实测截屏,边部显示异常,需要上述RGBA->ARGB处理, 此处理耗时,待优化
-
onActivityResult
回调有可能不能触发, 参考之前wiki中的处理方案 -
onImageAvailable
会执行多次,单张截屏需要及时把imageReader
close掉
tell me how get back to sunshine