Android实现屏幕录制的方式介绍两种,第一种是通过adb shell命令,还一种使用SDK的提供的方法实现.

  • adb shell 命令

语法: screenrecord [options] <filename>

Sample:adb shell screenrecord /sdcard/demo.mp4 开始录制(录制手机屏幕; 视频格式为mp4,存放到手机sd卡里,默认录制时间为180s)参数: --sizeadb shell screenrecord --size 1280*720 /sdcard/demo.mp4指定视频分辨率大小 (指定分辨率为1280*720;不指定则默认使用手机的分辨率,为获得最佳效果,请使用设备上的高级视频编码(AVC)支持的大小)参数: --bit-rateadb shell screenrecord --bit-rate 6000000 /sdcard/demo.mp4 指定视频的比特率 (指定视频的比特率为6Mbps; 如果不指定则默认为4Mbps, 你可以增加比特率以提高视频质量或为了让文件更小而降低比特率)参数: --time-limitadb shell screenrecord  --time-limit 10 /sdcard/demo.mp4 限制录制时间 (限制视频录制时间为10s; 如果不限制,默认180s)参数: --verboseadb shell screenrecord --time-limit 10 --verbose /sdcard/demo.mp4在命令行显示录屏Log如下:xxxx:/ # screenrecord --time-limit 10 --verbose /sdcard/demo.mp4Main display is 1080x2160 @60.00fps (orientation=0)Configuring recorder for 1080x2160 video/avc at 4.00MbpsContent area is 1080x2160 at offset x=0 y=0Time limit reachedEncoder stopping; recorded 34 frames in 10 secondsStopping encoder and muxerExecuting: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/demo.mp4Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/demo.mp4 }Broadcast completed: result=0参数: --bugreport添加额外的信息,例如时间戳覆盖,这有助于捕获用于演示错误的视频参数: --help查看帮助导出视频:adb pull /sdcard/demo.mp4

如果在APP中使用,我们可以通过Process p = Runtime.getRuntime().exec(cmd)来调用shell命令.但是只有system app才能调用,可以在manifest节点中添加android:sharedUserId="android.uid.system"拥有系统级的权限

  • 通过MediaProjection实现

1.动态申请录音和外部存储权限:

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 10);}

2.获取屏幕录制的权限

    MediaProjectionManager manager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);Intent intent = new Intent(manager.createScreenCaptureIntent());startActivityForResult(intent, REQUEST_CODE);

3.启动屏幕录制服务

    Intent service = new Intent(this, ScreenRecordService.class);service.putExtra("resultCode", resultCode);service.putExtra("data", data);service.putExtra("mWidthPixels", mWidthPixels);service.putExtra("mHeightPixels", mHeightPixels);service.putExtra("mDensityDpi", mDensityDpi);startService(service);

屏幕录制服务

public class ScreenRecordService extends Service {private static final String TAG = "ScreenRecordService";private WindowManager mWindowManager;private WindowManager.LayoutParams wmParams;private LinearLayout mFloatLayout;private MediaProjection mMediaProjection;private MediaRecorder mMediaRecorder;private VirtualDisplay mVirtualDisplay;private boolean isScreenRecord;private int mScreenDensity, mWidthPixels, mHeightPixels;@Overridepublic IBinder onBind(Intent intent) {
//        return new MyBinder();return null;}@Overridepublic void onCreate() {super.onCreate();initView();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {int resultCode = intent.getIntExtra("resultCode", -1);Intent data = intent.getParcelableExtra("data");mWidthPixels = intent.getIntExtra("mWidthPixels", 720);mHeightPixels = intent.getIntExtra("mHeightPixels", 1080);mScreenDensity = intent.getIntExtra("mDensityDpi", 1);Log.d(TAG, "initData  -->  mScreenDensity: " + mScreenDensity + "  mWidthPixels: " + mWidthPixels + "  mHeightPixels: " + mHeightPixels);mMediaProjection = ((MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE)).getMediaProjection(resultCode, data);return super.onStartCommand(intent, flags, startId);}private void startRecorder() {Log.d(TAG, "startRecord");isScreenRecord = true;createMediaRecorder();createVirtualDisplay(); // 在mediaRecorder.prepare() 之后调用,否则报错 failed to get surfacemMediaRecorder.start();}private void createVirtualDisplay() {mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG, mWidthPixels, mHeightPixels, mScreenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);}private void createMediaRecorder() {// 生成文件名SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");String curTime = formatter.format(new Date(System.currentTimeMillis()));mMediaRecorder = new MediaRecorder();//设置视频源: DEFAULT,Surface,CameramMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//设置视频输出格式: amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gppmMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//设置视频编码格式: default, H263, H264, MPEG_4_SPmMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//        //设置音频源
//        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
//
//        //设置音频编码格式: default,AAC,AMR_NB,AMR_WB
//        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//设置视频尺寸大小mMediaRecorder.setVideoSize(mWidthPixels, mHeightPixels);//设置视频编码的码率mMediaRecorder.setVideoEncodingBitRate(5 * mWidthPixels * mHeightPixels);   // mWidthPixels * mHeightPixels//设置视频编码的帧率mMediaRecorder.setVideoFrameRate(60);   // 30//设置视频输出路径mMediaRecorder.setOutputFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/Ansen_" + curTime + ".mp4");try {mMediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();Log.e(TAG, e.getMessage());}Log.d(TAG, "VideoSize: " + mWidthPixels + " X " + mHeightPixels + "  VideoEncodingBitRate: "+ (5 * mWidthPixels * mHeightPixels) + "  +VideoFrameRate: " + "60");}private void initView() {mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);wmParams = new WindowManager.LayoutParams();wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 设置window type为TYPE_SYSTEM_ALERTwmParams.format = PixelFormat.RGBA_8888;// 设置图片格式,效果为背景透明wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)wmParams.gravity = Gravity.LEFT | Gravity.TOP;// 默认位置:右下角wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;wmParams.x = (ScreenUtils.getScreenWidth(getApplicationContext()) - wmParams.width) / 2;// 设置x、y初始值,相对于gravitywmParams.y = 10;// 浮动窗口布局mFloatLayout = (LinearLayout) LayoutInflater.from(getApplication()).inflate(R.layout.screen_recorder, null);mWindowManager.addView(mFloatLayout, wmParams);final LinearLayout screenrecord = (LinearLayout) mFloatLayout.findViewById(R.id.screenrecord);final TextView title = (TextView) mFloatLayout.findViewById(R.id.screenrecord_title);final TextView close = (TextView) mFloatLayout.findViewById(R.id.screenrecord_close);final ImageView image = (ImageView) mFloatLayout.findViewById(R.id.play_stop);mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));// 设置监听浮动窗口的触摸移动View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// getRawX是触摸位置相对于屏幕的坐标,getX是相对于按钮的坐标wmParams.x = (int) event.getRawX() - mFloatLayout.getMeasuredWidth() / 2;Log.i(TAG, "RawX" + event.getRawX() + "  X" + event.getX());wmParams.y = (int) event.getRawY() - mFloatLayout.getMeasuredHeight() / 2 - 25;// 减25为状态栏的高度Log.i(TAG, "RawY" + event.getRawY() + "  Y" + event.getY());mWindowManager.updateViewLayout(mFloatLayout, wmParams);// 刷新return false;}};mFloatLayout.setOnTouchListener(mOnTouchListener);screenrecord.setOnTouchListener(mOnTouchListener);screenrecord.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (isScreenRecord) {image.setImageResource(R.mipmap.screen_record_play);title.setText("开始");stopRecord();} else {image.setImageResource(R.mipmap.screen_record_stop);title.setText("停止");startRecorder();}}});close.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d(TAG, "stopSelf");ScreenRecordService.this.stopSelf();}});}private void stopRecord() {Log.d(TAG, "stopRecord");isScreenRecord = false;mMediaRecorder.stop();mMediaRecorder.reset();}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy");if (isScreenRecord) {stopRecord();}mVirtualDisplay.release();mMediaProjection.stop();mWindowManager.removeView(mFloatLayout);}
}

代码地址

Android屏幕截图实现方式 & 系统截屏源码分析和三指截屏

Android长截屏(滚动截屏)实现原理

Android屏幕录制源码Demo下载相关推荐

  1. android实现阅读器底部菜单,android仿新闻阅读器菜单弹出效果实例(附源码DEMO下载)...

    开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉得是最后完成后发网站客户端的,可是这样体现不出一个功能一个功能的分析实现效果, ...

  2. 【转】Android 4.3源码的下载和编译环境的安装及编译

    原文网址:http://jingyan.baidu.com/article/c85b7a641200e0003bac95a3.html  告诉windows用户一个不好的消息,windows环境下没法 ...

  3. Android源码编译详解【四】:Android 6.0_源码的下载与编译

     1.AOSP源码下载  AOSP:即为"Android Open-Source Project"的缩写,中文意为 :"安卓开放源代码项目". Google官方 ...

  4. Android屏幕刷新——源码分析

    Android屏幕刷新原理--源码分析 文章目录 Android屏幕刷新原理--源码分析 概述 VSync信号 三级缓冲 源码分析 消息队列的同步屏障 参考资料 概述 Android系统每16ms(一 ...

  5. 【LeanEAP.NET】精益企业应用平台---源码Demo下载

    这个框架开发了很长时间,但是一个人开发,Demo和文档还不完善,现在把源代码上传上来,如果你有兴趣有时间并且了解框架开发,想为这个框架做点贡献,欢迎加入.如果你有项目外包也欢迎联系我. 下一步开发计划 ...

  6. K近邻算法讲解与python实现(附源码demo下载链接)

    k近邻算法概述 对应demo源码及数据:传送门 K近邻(k-Nearest Neighbor,简称kNN)算法,是一种应用很广泛的监督学习算法.它非常有效且易于掌握,其工作机制也很简单:给定测试样本, ...

  7. android+锁屏代码+下载,安卓客户端开发的锁屏源码demo下载,可直接应用到APP中

    安卓程序锁屏 好多安卓APP中都用到锁屏技术在这里只是一个Demo 但是可以直接运用到已经做好的APP中,在绘制锁屏中用到许多的Math函数. package com.weiqiang.lockpoi ...

  8. asp源码demo下载:微信公众号支付企业付款到零钱功能asp源码下载案例

    最近接到一个开发需求,一个企业想用微信支付里面的,企业付款到零钱功能,利用此功能来给用会发红包,因为微信支付里的红包功能一次要付款1块钱,太多,所以他想利用此功能来发红包,这样红包金额可以低到每次3角 ...

  9. android与html注册登录,Android登录注册源码

    Android登录注册源码 资源下载此资源下载价格为2D币,请先登录 资源文件列表 andoird96pk/.classpath , 348 andoird96pk/.project , 847 an ...

最新文章

  1. 初探linux内核编程,参数传递以及模块间函数调用
  2. python要学多久-零基础python培训需要学多久?
  3. Storm-源码分析-Stats (backtype.storm.stats)
  4. 计算机组成原理课程设计a,计算机组成原理课程设计报告.doc
  5. java 拦截jsp页面_JSP 过滤器
  6. 个人主页 — github + jekyll 搭建自己的个人主页
  7. Android万能布局检查器UI Automator Viewer使用教程、环境配置和Mac无法打开问题解决(uiautomatorviewer,android studio,layer,查看,错误)
  8. 根轨迹法和频率响应法设计PI控制器学习笔记
  9. letsencrypt证书-管理工具certbot
  10. form表单提交方式
  11. 【转载收藏】Unity预计算实时GI
  12. 后台管理系统 权限管理
  13. 手机品牌是否一定要自研芯片
  14. android跨应用调用方法是,Android如何实现不同应用之间的调用
  15. Sketch for UX Design Sketch UX设计教程 Lynda课程中文字幕
  16. 黑马程序员——阿龙的学习历程——Java初见
  17. 串口硬盘和并口硬盘的区别
  18. 码一些有用的东西网站的域名被拦截怎么办? 教你快速解除各种拦截
  19. OpenCV——LCC(Local Color Correction)的Python复现
  20. 加法器的实现(半加器,全加器,行波进位加法器,超前进位加法器,流水线加法器)

热门文章

  1. 目标检测算法SSD论文解读
  2. 脑机接口(BCI)的认识及EEG数据预处理介绍
  3. 番茄闹钟二(引入react-router)
  4. 苹果手机相册删除的照片怎么恢复
  5. python pip 多个版本冲突问题 完美解决
  6. 操作系统开发--什么是内核?
  7. Asix2搭建Spring-MVC的WebService
  8. C# winform项目使用腾讯云人像变换api对选定图片进行人像动漫化
  9. 招商头条:税务总局研究降低增值税率实施方案;宜昌签约20个项目总投资157.45亿元
  10. 【科研系列】专利检索工具及方法简单介绍