美文网首页程序员
Android截屏、录屏工具

Android截屏、录屏工具

作者: Tyhj | 来源:发表于2018-10-25 10:54 被阅读0次
    wallhaven-533030.jpg

    颜色拾取器分析

    有时候会用到颜色拾取器这样的东西来查看屏幕上的颜色值,一直是用Pixolor这个软件来看颜色的;很方便,点哪里显示哪里,也没有延迟,以为是什么黑科技;我注意到一个细节,如果只是切换屏幕,颜色拾取器不会更新,只有移动拾取器才更新选中;可以确定是截屏来实现的了,那就简单了,截屏获取像素点的颜色值就好了

    录屏和截屏

    网上看了一下,截屏大概分为保存View为图像和调用录屏服务两种办法,录屏是比较好的办法,可以在APP外截屏,所以简单的封装了一下

    集成方法:

    Step 1. Add the JitPack repository to your build file

    allprojects {
            repositories {
                ...
                maven { url 'https://jitpack.io' }
            }
        }
    
    

    Step 2. Add the dependency

    dependencies {
                implementation 'com.github.tyhjh:ScreenShot:v1.0.1'
        }
    

    截屏

    简单使用

    主要分为两步,第一步是开启录屏;第二步就可以直接获取截屏,返回Bitmap
    截图的过程录屏是开启的,录屏开启就可以进行截屏,操作完需要关闭录屏
    截屏过程很快,效果很好

    //第一次会自动申请录屏权限
    ScreenRecordUtil.getInstance().screenShot(this, new OnScreenShotListener() {
                @Override
                public void screenShot() {
                //可以获取截图,可以多次调用
                iv_pre.setImageBitmap(ScreenRecordUtil.getInstance().getScreenShot());
                //最后关闭录屏服务
                ScreenRecordUtil.getInstance().destroy();
                }
            });
    

    如果是APP外截屏则开启悬浮窗服务,可以通过操作悬浮窗进行截屏
    参考文章:Android 截屏方式整理Android录屏(5.0+)

    截屏实现代码

    1.初始化一个MediaProjectionManager

    MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    

    2.创建并启动Intent

    startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(),REQUEST_MEDIA_PROJECTION);
    

    3.在onActivityResult中拿到MediaProjection

    mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
    

    4.设置VirtualDisplay将图像和展示的View关联起来。一般来说我们会将图像展示到SurfaceView,这里为了为了便于拿到截图,我们使用ImageReader,他内置有SurfaceView。

    mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
    mScreenWidth, mScreenHeight, mScreenDensity,
    DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
    mImageReader.getSurface(), null, null);
    

    5.通过ImageReader拿到截图

    Image image = null;
    image = mImageReader.acquireLatestImage();
    while (image == null) {
        SystemClock.sleep(10);
        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();
    return bitmap;
    

    6.注意截屏之后要及时关闭VirtualDisplay ,因为VirtualDisplay 是十分消耗内存和电量的。

    if (mVirtualDisplay == null) {
                return;
    }
    mVirtualDisplay.release();
    mVirtualDisplay = null;
    
    

    录屏

    简单使用

    录屏和截屏差不多,只是截屏的时候只是设置了一个ImageReader去获取图像数据,而录屏是设置一个SurfaceView去接收内容,获取视频流,然后通过MediaCodec来实现视频的硬编码,然后保存为视频文件

    v2-24d825761d500ae9a0bf42e4c7a32c88_hd.png-69.3kBv2-24d825761d500ae9a0bf42e4c7a32c88_hd.png-69.3kB

    初始化录屏的大小和码率

    //码率为32M
    private int screenRecordBitrate = 32 * 1024 * 1024;
    
    ScreenRecordUtil.getInstance().init(ScreenUtil.SCREEN_WIDTH, ScreenUtil.SCREEN_HEIGHT, screenRecordBitrate);
    

    开始录屏,设置输出文件

    String savePath = MyApplication.baseDir + System.currentTimeMillis() + ".mp4";
    //开始录屏
    ScreenRecordUtil.getInstance().start(MainActivity.this, savePath);
    

    停止录屏

    new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(60 * 1000);
                        //结束录屏
                       ScreenRecordUtil.getInstance().destroy();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    

    录屏具体实现

    参考文章:Android视频录制--屏幕录制

    1.在 AndroidManifest 中添加权限,Android 6.0 加入的动态权限申请,如果应用的 targetSdkVersion 是 23,申请敏感权限还需要动态申请

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    

    中间操作和截屏一样,就是准备开启录屏

    5.创建虚拟屏幕,这一步就是通过 MediaProject 录制屏幕的关键所在,VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 参数是指创建屏幕镜像,所以我们实际录制内容的是屏幕镜像,但内容和实际屏幕是一样的,并且这里我们把 VirtualDisplay 的渲染目标 Surface 设置为 MediaRecordergetSurface,后面我就可以通过 MediaRecorder 将屏幕内容录制下来,并且存成 video 文件

    private void createVirtualDisplay() {
      virtualDisplay = mediaProjection.createVirtualDisplay(
            "MainScreen",
            width,
            height,
            dpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mediaRecorder.getSurface(),
            null, null);
    }
    

    6.录制屏幕数据,这里利用 MediaRecord 将屏幕内容保存下来

    private void initRecorder() {
      File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".mp4");
      mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
      mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
      mediaRecorder.setOutputFile(file.getAbsolutePath());
      mediaRecorder.setVideoSize(width, height);
      mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
      mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
      mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
      mediaRecorder.setVideoFrameRate(30);
      try {
        mediaRecorder.prepare();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    
    public boolean startRecord() {
      if (mediaProjection == null || running) {
        return false;
      }
      initRecorder();
      createVirtualDisplay();
      mediaRecorder.start();
      running = true;
      return true;
    }
    

    项目地址:https://github.com/tyhjh/ScreenShot

    相关文章

      网友评论

        本文标题:Android截屏、录屏工具

        本文链接:https://www.haomeiwen.com/subject/rosqtqtx.html