问题原因:
其主要原因:是webview渲染方式所导致;只需要AndroidManifest.xml中设置属性Android:hardwareAccelerated=”false”。
由于WebView内部所使用的Chromium实现是采用硬件加速渲染还是软件渲染,这里还是比较复杂的。根据android的View结构,WebView的内容需要通过一个onDraw(Canvas c)来完成绘制。为了将Chromium渲染网页的结果绘制到该Canvas中,需要两组绘图函数组,第一组用来软件渲染,第二组用来硬件加速渲染。而这两组函数需要使用Android内部函数,这决定了目前WebView只能同Android AOSP代码一起编译,而不能像应用程序一样,只是依赖于Android SDK/NDK来编译。下图是当用户界面或者网页需要绘制的时候,绘图的基本过程:
这里Chromium的合成器具有两种能力,就是包含支持软件渲染的软件渲染器和硬件加速渲染的渲染器。当用户界面所对应的画布(canvas)是硬件加速的话,那么内部采用硬件渲染机制。如果不是硬件加速的话,那么采用软件渲染机制。当用户的界面设置为硬件加速的时候(开发者可以在应用程序的AndroidManifest.xml中设置属性android:hardwareAccelerated=”true”),那么用户界面对应的画布即为硬件加速,否则即为软件渲染方式。所以,具体Chromium WebView采用什么样的方式,取决于调用WebView的应用程序的设置方式(默认是硬件加速)。 (关闭硬件加速会很卡顿,体验不好,不推荐)
————————————————
版权声明:本文为CSDN博主「ge673551532」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ge673551532/article/details/76103686
解决思路,录屏取其中的一帧为截图;
2. 截取非含当前应用的屏幕部分(最佳官方方案)
Android 在5.0 之后支持了实时录屏的功能。通过实时录屏我们可以拿到截屏的图像。同时可以通过在Service中处理实现后台的录屏。具体的类讲解大家自行网上查阅。
大体步骤:
1.初始化一个MediaProjectionManager。
MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager)getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
2.创建intent,并启动Intent。注意这里是startActivityForResult
startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
3.在onActivityResult中拿到Mediaprojection。
mResultCode = resultCode;
mResultData = data;
mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, mResultData);
4.设置VirtualDisplay 将图像和展示的View关联起来。一般来说我们会将图像展示到SurfaceView,这里为了为了便于拿到截图,我们使用ImageReader,他内置有SurfaceView。
mImageReader = ImageReader.newInstance(windowWidth, windowHeight,
0x1
,
2
);
//ImageFormat.RGB_565
mVirtualDisplay = mMediaProjection.createVirtualDisplay(
"screen-mirror"
,
windowWidth, windowHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(),
null
,
null
);
5.通过ImageReader拿到截图
strDate = dateFormat.format(new java.util.Date());
nameImage = pathImage + strDate + ".png";
Image image = mImageReader.acquireLatestImage();
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();
Log.i(TAG, "image data captured");
if (bitmap != null) {
try {
File fileImage = new File(nameImage);
if (!fileImage.exists()) {
fileImage.createNewFile();
Log.i(TAG, "image file created");
}
FileOutputStream out = new FileOutputStream(fileImage);
if (out != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
Intent media = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(fileImage);
media.setData(contentUri);
this.sendBroadcast(media);
Log.i(TAG, "screen image saved");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
6.注意截屏之后要及时关闭VirtualDisplay ,因为VirtualDisplay 是十分消耗内存和电量的。
private void stopVirtual() {
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
mVirtualDisplay = null;
Log.i(TAG, "virtual display stopped");
}