Android 截取手机屏幕两种实现方法

Android 截取手机屏幕两种实现方法

最近在开发的过程中,遇到了一个需要截取屏幕保存为图片的需求,具体为截取webview的视图保存图片。

方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法:

public void printScreen(View view) { String imgPath = "/sdcard/test.png"; view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); if (bitmap != null) { try { FileOutputStream out = new FileOutputStream(imgPath); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); } catch (Exception e) { e.printStackTrace(); } } }

这个方法在很多情况下都是没有问题的,比如说截取imageview,TextView,甚至otherview.getRootView();都没问题,但在WebView上就会出现webview的部分截取完缺少页面里的一些内容的情况,比如说用webview打开这个(https://miqt.github.io/jellyfish/)界面,截取的图片就会有问题,具体表现为网页中游动的水母没有显示在截取的图片上。

方法2:使用Android系统提供的服务Context.MEDIA_PROJECTION_SERVICE,进行截图操作。

Demo源码:https://github.com/miqt/CapWindow

关键部分代码解析:↓

发送截图请求

final MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); Intent intent = projectionManager.createScreenCaptureIntent(); startActivityForResult(intent, REQUEST_CODE);

接收返回的结果:

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); handleScreenShotIntent(resultCode, data); } private void handleScreenShotIntent(int resultCode, Intent data) { onScreenshotTaskBegan(); final MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); final MediaProjection mProjection = projectionManager.getMediaProjection(resultCode, data); Point size = Utils.getScreenSize(this); final int mWidth = size.x; final int mHeight = size.y; final ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat .RGBA_8888, 2); final VirtualDisplay display = mProjection.createVirtualDisplay("screen-mirror", mWidth, mHeight, DisplayMetrics.DENSITY_MEDIUM, DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, mImageReader.getSurface(), null, null); mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader mImageReader) { Image image = null; try { image = mImageReader.acquireLatestImage(); if (image != null) { final Image.Plane[] planes = image.getPlanes(); if (planes.length > 0) { final ByteBuffer buffer = planes[0].getBuffer(); int pixelStride = planes[0].getPixelStride(); int rowStride = planes[0].getRowStride(); int rowPadding = rowStride - pixelStride * mWidth; // create bitmap Bitmap bmp = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888); bmp.copyPixelsFromBuffer(buffer); Bitmap croppedBitmap = Bitmap.createBitmap(bmp, 0, 0, mWidth, mHeight); saveBitmap(croppedBitmap);//保存图片 if (croppedBitmap != null) { croppedBitmap.recycle(); } if (bmp != null) { bmp.recycle(); } } } } catch (Exception e) { e.printStackTrace(); } finally { if (image != null) { image.close(); } if (mImageReader != null) { mImageReader.close(); } if (display != null) { display.release(); } mImageReader.setOnImageAvailableListener(null, null); mProjection.stop(); onScreenshotTaskOver(); } } }, getBackgroundHandler()); }

这个方法类似使用手机的系统截屏(音量下键+电源键),能够完美的吧当前原模原样的屏幕截取下来,并且修改保存方法的话甚至可以屏幕录像,但相比于第一种方法,它的缺点是完全和界面上的view没有关系,并且在调用这个服务的时候,会弹出一个权限确认的弹框。另外需要注意,这一方法只能在Android 5.0的系统设备上适用。

总结:

总而言之,这两种方法各有利弊,使用的时候要根据自己的实际需求做出选择。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2024-11-02 16:00:11

Android 截取手机屏幕两种实现方法的相关文章

解析Android截取手机屏幕两种实现方案

最近在开发的过程中,遇到了一个需要截取屏幕保存为图片的需求,具体为截取webview的视图保存图片. 方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法: public void printScreen(View view) { String imgPath = "/sdcard/test.png"; view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap

Android 手机防止休眠的两种实现方法

Android 手机防止休眠的两种实现方法 实现这一功能的方法有两种, 一种是在Manifest.xml文件里面声明. 一种是在代码里面修改LayoutParams的标志位. 具体如下: 1.在Manifest.xml文件里面用user-permission声明.代码如下: < uses-permission android:name="android.permission.WAKE_LOCK" > < /uses-permission > 这种方法,在安装ap

Android注册广播的两种方法分析_Android

本文实例分析了Android注册广播的两种方法.分享给大家供大家参考,具体如下: 1. 在AndroidManifest.xml文件中注册. 好处:一旦应用程序被安装到手机里,BroadCast Receiver就开始生效.无论应用程序进程是否运行,运用程序是否在开启状态下都可以接受到广播事件. <receiver android:name=".receiver.SMSReceiver" > <intent-filter android:priority="

Android注册广播的两种方法分析

本文实例分析了Android注册广播的两种方法.分享给大家供大家参考,具体如下: 1. 在AndroidManifest.xml文件中注册. 好处:一旦应用程序被安装到手机里,BroadCast Receiver就开始生效.无论应用程序进程是否运行,运用程序是否在开启状态下都可以接受到广播事件. <receiver android:name=".receiver.SMSReceiver" > <intent-filter android:priority="

Android获取手机屏幕宽高、状态栏高度以及字符串宽高信息的方法

  Android获取手机屏幕宽高.状态栏高度以及字符串宽高信息的方法         这篇文章主要介绍了Android获取手机屏幕宽高.状态栏高度以及字符串宽高信息的方法,涉及Android获取文字宽高.状态栏高度.textView宽度及屏幕尺寸的相关技巧,需要的朋友可以参考下 首先定义TextView对象commentText 获取文字的宽高: ? 1 2 3 4 5 6 7 8 TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLA

Android时分秒计时器的两种实现方法_Android

可能我们在开发中会时常用到计时器这玩意儿,比如在录像的时候,我们可能需要在右上角显示一个计时器.这个东西其实实现起来非常简单. 只需要用一个控件Chronometer,是的,就这么简单,我都不好意思讲述一下了. <Chronometer android:layout_width="wrap_content" android:layout_height="wrap_content" android:format="%s" android:id

Android之Intent附加数据的两种实现方法

本文实例讲述了Android之Intent附加数据的两种实现方法.分享给大家供大家参考.具体如下: 第一种写法,用于批量添加数据到Intent: Intent intent = new Intent(); Bundle bundle = new Bundle(); //该类用作携带数据 bundle.putString("name", "林计钦"); intent.putExtras(bundle); //为意图追加额外的数据,意图原来已经具有的数据不会丢失,但ke

Android时分秒计时器的两种实现方法

可能我们在开发中会时常用到计时器这玩意儿,比如在录像的时候,我们可能需要在右上角显示一个计时器.这个东西其实实现起来非常简单. 只需要用一个控件Chronometer,是的,就这么简单,我都不好意思讲述一下了. <Chronometer android:layout_width="wrap_content" android:layout_height="wrap_content" android:format="%s" android:id

Android编程获取手机屏幕分辨率大小的方法

本文实例讲述了Android编程获取手机屏幕分辨率大小的方法.分享给大家供大家参考,具体如下: import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.widget.TextView; public class A03Activity extends Activity { private TextView mTextView01; /** C