Android实现截屏功能

 更新时间:2021年07月11日 09:55:14   作者:爱乐写代码  
这篇文章主要为大家详细介绍了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,没有难的东西,需要不停的学习和积累

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • android handler.post和handler.sendMessage的区别和联系

    android handler.post和handler.sendMessage的区别和联系

    handler.post和handler.sendMessage本质上是没有区别的,都是发送一个消息到消息队列中,而且消息队列和handler都是依赖于同一个线程的。接下来通过本文给大家分享android handler.post和handler.sendMessage的区别和联系,一起看看吧
    2017-08-08
  • Android计时与倒计时实现限时抢购的5种方法

    Android计时与倒计时实现限时抢购的5种方法

    这篇文章主要为大家详细介绍了Android计时与倒计时实现限时抢购的5种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Android应用隐私合规检测实现方案详解

    Android应用隐私合规检测实现方案详解

    这篇文章主要介绍了Android应用隐私合规检测实现方案,我们需要做的就是提前检测好自己的应用是否存在隐私合规问题,及时整改过来,下面提供Xposed Hook思路去检测隐私合规问题,建议有Xposed基础的童鞋阅读,需要的朋友可以参考下
    2022-07-07
  • Android自定义View实现拖拽效果

    Android自定义View实现拖拽效果

    这篇文章主要为大家详细介绍了Android自定义View实现拖拽效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Android 通过Messager与Service实现进程间双向通信案例详解

    Android 通过Messager与Service实现进程间双向通信案例详解

    这篇文章主要介绍了Android 通过Messager与Service实现进程间双向通信案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Android中button按钮怎么设置圆角

    Android中button按钮怎么设置圆角

    在android开发中,Button是使用很频繁的一种控件,而android提供的原生Button是很规矩的矩形外观,有时候缺乏美感,而相反,圆角按钮则可以提升美感,这篇文章主要给大家介绍了关于Android中button按钮怎么设置圆角的相关资料,需要的朋友可以参考下
    2023-07-07
  • Android编程获取组件尺寸大小的方法

    Android编程获取组件尺寸大小的方法

    这篇文章主要介绍了Android编程获取组件尺寸大小的方法,结合实例形式分析了Android绘制组件之前获取该组件大小的3种常见操作技巧,需要的朋友可以参考下
    2017-03-03
  • Android实现画板功能(二)

    Android实现画板功能(二)

    这篇文章主要为大家详细介绍了Android实现画板功能的第二篇,使用imageView,bitmap方式实现画板,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • Android RefreshLayout实现下拉刷新布局

    Android RefreshLayout实现下拉刷新布局

    这篇文章主要为大家详细介绍了Android RefreshLayout实现下拉刷新布局,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Android学习教程之日历控件使用(7)

    Android学习教程之日历控件使用(7)

    这篇文章主要为大家详细介绍了Android学习教程之日历控件操作代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11

最新评论