android视频截屏&手机录屏实现

问题

在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以通过activity的顶层view DecorView获取一个bitmap,得到就是当前activity上面的全部视图。

 View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        Bitmap ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);
        view.destroyDrawingCache();

如果activity中包含一些视频播放器比如SurfaceView GLSurfaceView
TextureView,在调用截屏代码会发现播放视频的部分是黑屏的,原因是这几种视频渲染的view通过以上代码拿到的是缓冲区不是真正的图像。

解决办法

android5.0以上系统提供了一个 MediaProjectionManager
类来对手机进行录屏操作,也支持获取手机的Image图像的操作,知道了这些我们就可以通过提供的api来进行截屏操作了。

这里通过Service来操作截屏和录屏的api

1.绑定截屏的Service

 Intent intent = new Intent(this, ScreenService.class);
 bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

 public void onServiceConnected(ComponentName className, IBinder service) {
             DisplayMetrics metrics = new DisplayMetrics();
             getWindowManager().getDefaultDisplay().getMetrics(metrics);
             ScreenService.RecordBinder binder = (ScreenService.RecordBinder) service;
             recordService = binder.getRecordService();
             recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);
             mButton.setEnabled(true);
             mButton.setText(recordService.isRunning() ? "结束" : "开始");
  }

2.请求权限 onActivityResult 方法中回调。

 Intent captureIntent = projectionManager.createScreenCaptureIntent();
 startActivityForResult(captureIntent, RECORD_REQUEST_CODE);

  成功后
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {

             //######## 截屏逻辑 ########
             mediaProjection = projectionManager.getMediaProjection(resultCode, data);
             recordService.setMediaProject(mediaProjection);
             recordService.initImageReader();

         }
  }

3. 获取截屏

  @Override
  public void onClick(View view) {

    //########  截屏逻辑 ########
     Bitmap bitmap = recordService.getBitmap();
     mImageView.setImageBitmap(bitmap);
  }

录屏

录屏需要初始化一些录屏参数,输入麦克风类型视频类型,保存路径等

 private void initRecorder() {
         mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
         mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
         mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
         mediaRecorder.setOutputFile(
                 getSavePath() + System.currentTimeMillis() + ".mp4");
         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();
         }
 }

开始录屏

  mediaRecorder.start();

保存路径


完整Service代码

public class ScreenService extends Service {
private MediaRecorder mediaRecorder;
private VirtualDisplay virtualDisplay;
private boolean running;
private int width = 720;
private int height = 1080;
private int dpi;
private ImageReader mImageReader;
private MediaProjection mediaProjection;

 @Override
 public IBinder onBind(Intent intent) {
     return new RecordBinder();
 }


 @Override
 public void onCreate() {
     super.onCreate();
     running = false;
     mediaRecorder = new MediaRecorder();
 }


 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
     return super.onStartCommand(intent, flags, startId);
 }


 @Override
 public void onDestroy() {
     super.onDestroy();
 }


 public void setMediaProject(MediaProjection project) {
     mediaProjection = project;
 }


 public boolean isRunning() {
     return running;
 }


 public void setConfig(int width, int height, int dpi) {
     this.width = width;
     this.height = height;
     this.dpi = dpi;
 }


 /**
  * 开始录屏
  *
  * @return true
  */
 public boolean startRecord() {
     if (mediaProjection == null || running) {
         return false;
     }
     initRecorder();
     createVirtualDisplay();
     mediaRecorder.start();
     running = true;
     return true;
 }


 /**
  * 结束录屏
  *
  * @return true
  */
 public boolean stopRecord() {
     if (!running) {
         return false;
     }
     running = false;
     mediaRecorder.stop();
     mediaRecorder.reset();
     virtualDisplay.release();
     mediaProjection.stop();

     return true;
 }


 public void setMediaProjection(MediaProjection mediaProjection) {
     this.mediaProjection = mediaProjection;
 }


 /**
  * 初始化ImageRead参数
  */
 public void initImageReader() {
     if (mImageReader == null) {
         int maxImages = 2;
         mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, maxImages);
         createImageVirtualDisplay();
     }
 }


 /**
  * 创建一个录屏 Virtual
  */

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


 /**
  * 创建一个ImageReader Virtual
  */
 private void createImageVirtualDisplay() {
     virtualDisplay = mediaProjection
             .createVirtualDisplay("mediaprojection", width, height, dpi,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader
                     .getSurface(), null, null);
 }


 /**
  * 初始化保存屏幕录像的参数
  */
 private void initRecorder() {
     mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
     mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
     mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
     mediaRecorder.setOutputFile(
             getSavePath() + System.currentTimeMillis() + ".mp4");
     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();
     }
 }


 /**
  * 获取一个保存屏幕录像的路径
  *
  * @return path
  */
 public String getSavePath() {
     if (Environment.getExternalStorageState()
                    .equals(Environment.MEDIA_MOUNTED)) {
         String rootDir = Environment.getExternalStorageDirectory()
                                     .getAbsolutePath() + "/" +
                 "ScreenRecord" + "/";

         File file = new File(rootDir);
         if (!file.exists()) {
             if (!file.mkdirs()) {
                 return null;
             }
         }
         return rootDir;
     } else {
         return null;
     }
 }


 /**
  * 请求完权限后马上获取有可能为null,可以通过判断is null来重复获取。
  */
 public Bitmap getBitmap() {
     Bitmap bitmap = cutoutFrame();
     if (bitmap == null) {
         getBitmap();
     }
     return bitmap;
 }


 /**
  * 通过底层来获取下一帧的图像
  *
  * @return bitmap
  */
 public Bitmap cutoutFrame() {
     Image image = mImageReader.acquireLatestImage();
     if (image == null) {
         return null;
     }
     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);
     return Bitmap.createBitmap(bitmap, 0, 0, width, height);
 }


 public class RecordBinder extends Binder {
     public ScreenService getRecordService() {
         return ScreenService.this;
     }
 }

demo下载

github



作者:金威JW
链接:http://www.jianshu.com/p/2a330e3cfdac
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值