Android实现截屏功能
作者:爱乐写代码 发布时间:2022-10-25 04:36:52
标签:Android,截屏
导言
目前截屏的方法很多,root不适用,要么其他方法就是有局限性,而其中官方给出的方案最好—MediaProjection
介绍
Android 5.0以后开放的录屏API,取视频中的一帧数据,这样就可以实现截屏
步骤
在activity中授权,在service中完成初始化并截图,当然可以后台定时截图,但是6.0系统会有内存溢出的bug
1:build.gradle
compileSdkVersion 21
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.aile.screenshot"
multiDexEnabled true
minSdkVersion 21
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
2:在activity中授权
public void requestCapturePermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_MEDIA_PROJECTION:
if (resultCode == RESULT_OK && data != null) {
Service.setResultData(data);
startService(new Intent(this, Service.class));
finish();
}
break;
}
}
3:在service中初始化ImageReader,MediaProjection
private void createImageReader() {
mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
}
public void setUpMediaProjection() {
mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
}
}
4:在service中完成截图重要步骤:
private void startScreenShot() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
startVirtual();
}
}, 0);
handler.postDelayed(new Runnable() {
@Override
public void run() {
startCapture();
}
}, 50);
}
public void startVirtual() {
if (mMediaProjection != null) {
virtualDisplay();
} else {
setUpMediaProjection();
virtualDisplay();
}
}
private void virtualDisplay() {
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
//异常处理的核心
private void startCapture() {
Image image = null;
try {
image = mImageReader.acquireLatestImage();
} catch (IllegalStateException e) {
if (null != image) {
image.close();
image = null;
image = mImageReader.acquireLatestImage();
}
}
if (image == null) {
startScreenShot();
} else {
SaveTask mSaveTask = new SaveTask();
AsyncTaskCompat.executeParallel(mSaveTask, image);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
stopVirtual();
tearDownMediaProjection();
}
}, 0);
}
}
public class SaveTask extends AsyncTask<Image, Void, Bitmap> {
@Override
protected Bitmap 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();
return bitmap;
}
@Override
protected void onPostExecute(final Bitmap bitmap) {
super.onPostExecute(bitmap);
//处理bitmap的业务代码
}
5:Bitmap转IS流,指定区域截图
// 将Bitmap转换成InputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
//指定区域截图
Rect mRect = new Rect(51, 74, 58, 62);
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, true);
Bitmap bm = bitmapRegionDecoder.decodeRegion(mRect, null);
6:定时任务的处理
private Timer timer = new Timer();
public void shootByTime() {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
startScreenShot();
super.handleMessage(msg);
}
};
timer.schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}, 0, 100);
}
7:横竖屏的处理
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_PORTRAIT) {
mRect = new Rect(51, 775, 745, 47);
} else if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_LANDSCAPE) {
mRect = new Rect(54, 24, 545, 45);
}
}
8:还有很多,只需按照需求走就OK,没有难的东西,需要不停的学习和积累
来源:https://blog.csdn.net/ware00/article/details/80744465


猜你喜欢
- 本文实例讲述了C#调用存储过程的方法。分享给大家供大家参考,具体如下:CREATE PROCEDURE [dbo].[GetNameById
- Docker现在很火,容器技术看上不无所不能,但这实际上是一种误解,不要被炒作出来的泡沫迷住双眼,本文抛去炒作,理性地从Java程序员的角度
- 目录1、什么是LockSupport?2、两类基本API3、LockSupport本质4、LockSupport例子5、LockSuppor
- 由于CPU的计算频率非常高,每秒计算数十亿次,因此可以将CPU的时间从毫秒的维度进行分段,每一小段叫作一个CPU时间片。目前操作系统中主流的
- 使用淘宝ip地址库的api查询ip地址信息。TaobaoIPHelper.csusing System;using System.Coll
- 本文介绍了Android中js和原生交互的示例代码,分享给大家,具体如下:加载webview的类public class MainActiv
- 步骤一:1.查看Eclipse版本的eclipse--help--About Eclipse,在Eclipseplatfrom那行的Vers
- 前言:上篇C#进阶系列——WebApi接口传参不再困惑:传参详解介绍了WebApi参数的传递,这篇来看看WebApi里面异常的处理。关于异常
- 再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上
- byte:java中最小的数据类型。1字节/8位。-128(2^7)~127(2^7-1),默认值0。short:短整型,2字节/16位,取
- 首先是按行读取字符串import java.io.BufferedReader;import java.io.File;import jav
- 本文实例讲述了Android使用SharedPreferences存储数据的实现方法。分享给大家供大家参考,具体如下:编辑短信的时候,突然接
- 本文实例为大家分享了android自定义圆形倒计时显示控件的具体代码,供大家参考,具体内容如下先上效果图 - 倒计时结束代码块at
- 介绍前面的内容对Handler做了介绍,也讲解了如何使用handler,但是我们并不知道他的实现原理。本文从源码的角度来分析如何实现的。首先
- static修饰符是java里面非常常用的一个东西,用法也非常多。然而,在kotlin里竟然没有这个东西!那该如何替代呢?本文就总结了下ja
- 前言想在锁屏上面实现弹窗,第一个想法就是利用 WindowManager 设置 Window 的 Flag,通过设置 Flag 的显示优先级
- IntelliJ IDEA一个吸引人的地方在于,他有比较好的反编译工具,这让Eclipse用户牙痒痒。但不要紧,本文介绍如何在Eclipse
- 本文实例讲述了C#定时关闭窗体的方法,分享给大家供大家参考。具体方法如下:public partial class Form2 : Form
- 基本语法C#,又名Csharp,天朝喜欢叫C井。C#是一种面向对象的编程语言。在面向对象的程序设计方法中,程序有各种相互交互的对象组成。相同
- 本文实例为大家分享了Java实现UDP多线程在线咨询,供大家参考,具体内容如下1.发送的线程import java.io.BufferedR