本文实例为大家分享了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 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;

}

@Override

public boolean canScrollHorizontally() {

return canScrollHorizon && super.canScrollHorizontally();

}

@Override

public 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;

}

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

if (onPageChangeListener != null) {

onPageChangeListener.onScrolled(recyclerView, dx, dy);

}

}

@Override

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

int position = 0;

RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

//获取当前选中的itemView

View view = snapHelper.findSnapView(layoutManager);

if (view != null) {

//获取itemView的position

position = 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() {

@Override

public void onGlobalLayout() {

//会多次调用,执行完逻辑之后取消监听

recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

}

});

根据时间进行播放

private void convertCWACT(CW cw, int seconds,boolean isSeek) {

List cwacts = cw.getACT();

//如何是播放器跳转,先回到首页,清空所有item中的画板,防止从高时间跳转到低时间出现错误

if(isSeek){

position =0;

forbitLayoutManager.scrollToPosition(position);

forbitLayoutManager.setStackFromEnd(true);

for(int i=0;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实现录屏小功能相关推荐

  1. win10录屏工具_win10怎么录屏?这才是最长情陪伴你的录屏工具

    win10怎么录屏?现在看视频的用户是越来越多了,一些经验类的视频教程越来越多,不仅能够教我们学习技能,也能给我们看一些会员才能看的视频内容,他们怎么怎么做的呢?当然是电脑录屏了,由于现在的电脑基本上 ...

  2. Android Gradle 构建工具(Android Gradle Build Tools)是什么?

    转载地址:http://mrfu.me/android/2015/07/17/New_Android_Gradle_Build_Tools/ 译者地址:[翻]一览新的 Android Gradle 构 ...

  3. windows安装ffmpeg_免费实用的录屏工具!支持全屏、特定窗口、选定区域录制,支持添加水印、嵌入摄像头(附ffmpeg安装)...

    哈喽大家好,我是菌菌~ 在线授课.游戏录制.视频编辑.网上会议--现如今,视频录制非常火爆,一款好用的视频录制工具自然必不可少. 今天,菌菌就给大家分享3款免费又好用的电脑录屏工具,一起来看看吧! w ...

  4. android 新开发工具,Android开发人员必备的10个开发工具

    Android SDK 本身包含很多帮助开发人员设计.开发.测试和发布 Android 应用的工具,在本文中,我们将讨论 10 个最常用的工具. 1. Eclipse ADT Eclipse ADT  ...

  5. 测试android兼容性测试工具,Android兼容性测试工具Spoon

    android分布式测试工具. 简介 android众多的版本和机型给android app测试工作带来不小的挑战.Spoon通过将case分布式地执行.将执行结果更友好地展示出来,从而简化andro ...

  6. android 单位转换工具,Android单位转换工具类

    Android单位转换工具类 Android单位转换工具类主要由以下4部分构成 1.这个类不能被初始化 2.dip转px接口 3.sp转px接口 4.px转dip接口 代码如下: import and ...

  7. android app性能测试工具,Android 性能测试 - 内存

    1.内存了解 在Android App的性能优化的各个部分里,内存方面的知识较多且不易理解,内存的问题绝对是最令人头疼的一部分,需要对内存基础知识.内存分配.内存管理机制等非常熟悉,才能排查题. 1. ...

  8. Android集成开发工具——Android Studio

    Android Studio 是谷歌推出的一个Android集成开发工具,基于IntelliJ IDEA. 类似Eclipse ADT,Android Studio 提供了集成的 Android 开发 ...

  9. android pdf阅读工具,android pdf 阅读器开发, pdf demo, pdf第三方控件

    Activity调用的方法 public class PDFActivity extends Activity implements OnPageChangeListener { public sta ...

  10. android闹钟测试工具,android开发:AlarmManager闹钟管理器的实例

    1.AlarmManager,顾名思义,就是"提醒",是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的PendingIntent.通俗点,就是设置一 ...

最新文章

  1. 【iOS】中间透明的引导蒙层
  2. 机器学习建模神器PyCaret已开源!提升效率,几行代码轻松搞定模型
  3. IBM 消费者洞察报告,揭示 5G 娱乐时代的三大关键趋势
  4. Centos 7.X安装DB2 10.5
  5. 如何根据指定软件版本制作属于自己的puppet yum源
  6. GARFIELD@04-30-2005
  7. spark sql 优化心得
  8. 计算机系统如何禁止删除文件,电脑禁止安装删除文件 禁止复制电脑文件的方法...
  9. 杭电1861 游船出租
  10. Go 语言发布 2018 调查报告,最被诟病问题竟然是......
  11. 结合源码探讨Android距离传感器亮灭屏机制
  12. 'net’ 不是内部命令或外部命令,也不是可运行的程序或批处理文件 解决方法...
  13. Zabbix中文使用手册
  14. c位边上还有什么位_火箭少女海报一反常态,孟美岐取代yamy站C位,吴宣仪在边上...
  15. 数据挖掘 / 机器学习——决策树
  16. 线性代数入门指南:线性方程组
  17. linux shell 宏定义_一篇教会你写90%的shell脚本
  18. Equalize the Array(思维)
  19. Python 小试牛刀
  20. 小程序 | 小程序中常用的事件 + 事件对象的属性列表 +小程序事件传参 + 小程序全局配置 + 小程序页面配置 + 小程序发起网络数据请求

热门文章

  1. 数据库期末复习:选择题汇总
  2. git上传代码的账户名不是本人的问题
  3. [SinGuLaRiTy] 动态规划题目复习
  4. 追男妙计 三招搞定!
  5. java积分管理系统_积分兑换系统_超市积分管理
  6. 科研方法-X_LAB-方法总结和实践记录
  7. 2007年春节读书心得
  8. Https网址在线安全检测网站
  9. 【安装Oracle 12.2.0.1补丁】Oracle Database SAP Bundle Patch 12.2.0.1.220118 - 202202
  10. 前端是什么,是干嘛的