Android实现截屏功能
作者:爱乐写代码 时间:2022-10-25 04:36:52
导言
目前截屏的方法很多,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
标签:Android,截屏
0
投稿
猜你喜欢
C#使用IComparer自定义List类实现排序的方法
2021-06-28 04:28:09
Java Base64算法实际应用之邮件发送实例分析
2022-08-08 04:00:04
布隆过滤器面试如何快速判断元素是否在集合里
2022-10-17 15:55:19
Android编程使用Service实现Notification定时发送功能示例
2023-03-12 09:54:44
Android自定义view实现圆形、圆角和椭圆图片(BitmapShader图形渲染)
2022-10-08 07:51:35
java实现新浪微博Oauth接口发送图片和文字的方法
2023-11-29 01:43:04
UE4 Unlua 调用异步蓝图节点AIMoveTo函数示例详解
2022-04-12 05:35:41
c# 死锁和活锁的发生及避免
2023-05-28 00:45:49
安卓(Android)动态创建多个按钮并添加监听事件
2023-04-25 16:11:43
浅谈Java中几种常见的比较器的实现方法
2022-04-08 19:04:36
Android编程获取通知栏高度的方法
2023-10-23 22:50:24
Javaweb开发中通过Servlet生成验证码图片
2022-06-23 06:33:34
Android编程画图之抗锯齿解决方法
2022-12-17 12:03:54
Android返回键功能的实现方法
2021-10-01 12:54:53
Android自定义EditText实现登录界面
2022-07-03 11:59:25
Spring Batch批处理框架使用解析
2021-12-24 03:41:19
Spring入门实战之Profile详解
2021-10-03 19:08:34
android中sqlite的按条件查找的小例子
2021-06-18 03:39:33
Java使用Math.random()结合蒙特卡洛方法计算pi值示例
2023-05-10 10:43:13
C#程序提示“正由另一进程使用,因此该进程无法访问该文件”的解决办法
2022-06-27 04:34:11