android录屏功能
思路
android实现录屏功能有两种方案,一种是直接使用android自带的MediaProjectionManager实现录屏功能,第二种是是只录语音,用户的操作通过某种方式进行记录保存,最后通过某种协议进行播放。
两种方案各有各的优缺点,前者实现方式简单,但无法只录制特定区域的画面,并且生成的视频文件一般都比较大。后者实现较为繁琐,音频录制android7.0之前没有暂停方法,只能生成多个文件,然后对音频进行合成。用户的操作需要自己进行保存,播放时还原。播放器需要自定义生成。但后者的好处是可扩展性高,支持特定区域录制,并且生成的音频文件比较小。
需求
录制画板,画板要求可以更改颜色粗细,可以擦除。画板底部可以是白板,图片。图片要求是相机拍摄或者本地图片。可以播放录制内容;需要上传,所以文件要小,所有只能选择第二种方式。
github地址
整个项目生成的是一个文件夹,文件夹中包含一个MP3文件,一个cw协议文件(存储用户的操作),图片。整个画板是一个recyclerView,item中包含一个涂鸦画板,图片控件。播放时读取cw协议文件,按照时间一个个绘制,协议内容包含画板各个页的内容是空白画板还是图片,时间点,操作(切换图片/画线)。
音频
//开始录音if (mMediaRecorder == null) {mMediaRecorder = new MediaRecorder();}mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);mMediaRecorder.setOutputFile(mRecordFilePath);mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//amr_nb格式头部有6个字节的头信息try {mMediaRecorder.prepare();mMediaRecorder.start();isRunning = true;AudioUtil.startAudio();mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN, 1000);} catch (IOException e) {e.printStackTrace();}
/*** 合成amr_nb编码的音频* @param partsPaths* @param unitedFilePath*/public static void uniteAMRFile(List<String> partsPaths, String unitedFilePath) {try {File unitedFile = new File(unitedFilePath);FileOutputStream fos = new FileOutputStream(unitedFile);RandomAccessFile ra = null;for (int i = 0; i < partsPaths.size(); i++) {ra = new RandomAccessFile(partsPaths.get(i), "rw");if (i != 0) {ra.seek(6);}byte[] buffer = new byte[1024 * 8];int len = 0;while ((len = ra.read(buffer)) != -1) {fos.write(buffer,0,len);}File file = new File(partsPaths.get(i));if(file.exists()){file.delete();}}if(ra!=null){ra.close();}fos.close();} catch (Exception e) {e.printStackTrace();}}
音频播放
mediaPlayer = new MediaPlayer();mediaPlayer.setDataSource(path);mediaPlayer.prepare();mediaPlayer.start();
recyclerView
是否禁止滑动
public class ForbitLayoutManager extends LinearLayoutManager {private boolean canScrollHorizon = true;private boolean canScrollVertical = true;public ForbitLayoutManager(Context context) {super(context);}public ForbitLayoutManager(Context context, int orientation, boolean reverseLayout) {super(context, orientation, reverseLayout);}public ForbitLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}public void setCanScrollHorizon(boolean canScrollHorizon) {this.canScrollHorizon = canScrollHorizon;}public void setCanScrollVertical(boolean canScrollVertical) {this.canScrollVertical = canScrollVertical;}@Overridepublic boolean canScrollHorizontally() {return canScrollHorizon && super.canScrollHorizontally();}@Overridepublic boolean canScrollVertically() {return canScrollVertical && super.canScrollVertically();}
}
滑动时只滑动一页类似viewPage
mPagerSnapHelper = new PagerSnapHelper();mPagerSnapHelper.attachToRecyclerView(recyclerView);
获得当前是第几页,类似viewPage的pageSelect
public class RecyclerViewPageChangeListenerHelper extends RecyclerView.OnScrollListener {private SnapHelper snapHelper;private OnPageChangeListener onPageChangeListener;private int oldPosition = -1;//防止同一Position多次触发public RecyclerViewPageChangeListenerHelper(SnapHelper snapHelper, OnPageChangeListener onPageChangeListener) {this.snapHelper = snapHelper;this.onPageChangeListener = onPageChangeListener;}@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);if (onPageChangeListener != null) {onPageChangeListener.onScrolled(recyclerView, dx, dy);}}@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);int position = 0;RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();//获取当前选中的itemViewView view = snapHelper.findSnapView(layoutManager);if (view != null) {//获取itemView的positionposition = layoutManager.getPosition(view);}if (onPageChangeListener != null) {onPageChangeListener.onScrollStateChanged(recyclerView, newState);//newState == RecyclerView.SCROLL_STATE_IDLE 当滚动停止时触发防止在滚动过程中不停触发if (newState == RecyclerView.SCROLL_STATE_IDLE && oldPosition != position) {oldPosition = position;onPageChangeListener.onPageSelected(position);}}}public interface OnPageChangeListener {void onScrollStateChanged(RecyclerView recyclerView, int newState);void onScrolled(RecyclerView recyclerView, int dx, int dy);void onPageSelected(int position);}
}
获得当前选择的item(只能获得可视页面item)
View view = forbitLayoutManager.findViewByPosition(position);//有时会获取到null,是因为页面还没有渲染完成,可以使用recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//会多次调用,执行完逻辑之后取消监听recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);}});
根据时间进行播放
private void convertCWACT(CW cw, int seconds,boolean isSeek) {List<CWACT> cwacts = cw.getACT();//如何是播放器跳转,先回到首页,清空所有item中的画板,防止从高时间跳转到低时间出现错误if(isSeek){position =0;forbitLayoutManager.scrollToPosition(position);forbitLayoutManager.setStackFromEnd(true);for(int i=0;i<recyclerViewList.size();i++){View view = recyclerViewList.get(i);if(view!=null){SimpleDoodleView doodleView = view.findViewById(R.id.doodleView);doodleView.clear();}}}for (CWACT cwact : cwacts) {int time = cwact.getTime();if(isSeek?time > seconds:time != seconds){continue;}if ("switch".equals(cwact.getAction())) {//切换页面position = cwact.getCwSwitch().getIndex();forbitLayoutManager.scrollToPosition(position);forbitLayoutManager.setStackFromEnd(true);} else if ("line".equals(cwact.getAction())) {//划线if(position>recyclerViewList.size()-1){continue;}View view = recyclerViewList.get(position);if(view!=null){SimpleDoodleView doodleView = view.findViewById(R.id.doodleView);doodleView.setDrawPath(cwact.getLine());}} else if ("clear".equals(cwact.getAction())) {//清屏if(position>recyclerViewList.size()-1){continue;}View view = recyclerViewList.get(position);if(view!=null){SimpleDoodleView doodleView = view.findViewById(R.id.doodleView);doodleView.clear();}}}}
android录屏功能相关推荐
- Android 录屏功能的实现
最近开发中,要实现录屏功能,查阅相关资料,发现调用 MediaProjectionManager的api 实现录屏功能即可: import android.Manifest; import andro ...
- android录屏功能的实现
近期项目需要录屏功能,功能已实现,特此记录一下. //<----------------------------------录屏开始------------------------------- ...
- android 手机录屏功能,Android录屏功能的实现
最近做一个Android开发的项目用到了录屏的功能,开始查阅了一些资料和博客,基本上都是在讨论ROOT的.直到后来在github上看到一个比较新的代码,才恍然发现,Android 5.0时候开放了一个 ...
- 如何调用android录屏功能吗,Android录屏功能的实现
最近做一个Android开发的项目用到了录屏的功能,开始查阅了一些资料和博客,基本上都是在讨论ROOT的.直到后来在github上看到一个比较新的代码,才恍然发现,Android 5.0时候开放了一个 ...
- webRTC(二十一):android 录屏功能
效果 录屏和截屏的思路基本一致,请看详细代码 布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/an ...
- 【Android】录屏功能实现——MediaProjection
目录 Android录屏功能实现-MediaProjection 概述 工具类 作用 过程 权限申请 连接服务 开始录制 停止录制 总结 不积跬步,无以至千里:不积小流,无以成江海.要沉下心来,诗和远 ...
- android 实现手机录屏功能,基于MediaProjection实现Android移动手机截屏和录屏功能
Android软件应用经常要求实现截屏和录屏的功能,那么如何实现Android软件截屏和录屏功能呢?本文将介绍基于MediaProjection实现Android移动手机截屏和录屏功能. MediaP ...
- Android 和dialog 防录屏功能失效,游戏防录屏功能失效.
1. 正常禁止录屏在Activity的onCreate()方法中调用如下代码,但是在小米,OPPO等设备上只能禁止截屏,无法禁止录屏. @Overrideprotected void onCreate ...
- android 手机录屏功能,手机自带录屏功能在哪里找?轻松搞定屏幕录制
手机的录屏功能如何使用?智能手机发展到现在,除了无线通话功能.讯息发送功能之外,又逐渐发展出拍照功能.上网功能.各类应用交互功能.尤其近几年在手机上看视频成为打发碎片化时间的重要消遣,在手机上录屏的需 ...
最新文章
- 格莱泽检验matlab,计量经济学实验指导书
- Flask基础知识点1
- access开发内销核算系统
- iReport工具的使用(三)
- 理解Caffe的网络模型
- proxychains-ng 工作原理分析
- mysql命令行的几个用法
- python 列表 remove()函数使用详解
- 12c rman中输入sql命令
- 强者不能恒强,偏向虎山行
- 第四章表单与文件-笔记-验证
- javaScript,Dwr分页模拟
- WINCC冗余、上位机冗余详细教程
- ConfuserEx 脱壳软件 使用教程
- 能源DEA--对于业务和环境评估的规模报酬与规模损害
- 微信小程序如何实现点击链接跳转到手机自带浏览器
- 【信号与系统】如何求系统的冲激响应和阶跃响应
- Altium Designer 21 安装教程
- xp cmd命令大全
- 腾讯《活着》频道JS图片轮换效果解析