欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-21 17:53:28
本文介绍了android视频截屏&手机录屏实现代码,分享给大家,希望对大家有帮助 问题 在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以...

本文介绍了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);

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

成功后

 @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);
 }

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

录屏

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

 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();

保存路径

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

完整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下载


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