android 录屏工具,android实现录屏小功能
本文实例为大家分享了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实现录屏小功能相关推荐
- win10录屏工具_win10怎么录屏?这才是最长情陪伴你的录屏工具
win10怎么录屏?现在看视频的用户是越来越多了,一些经验类的视频教程越来越多,不仅能够教我们学习技能,也能给我们看一些会员才能看的视频内容,他们怎么怎么做的呢?当然是电脑录屏了,由于现在的电脑基本上 ...
- Android Gradle 构建工具(Android Gradle Build Tools)是什么?
转载地址:http://mrfu.me/android/2015/07/17/New_Android_Gradle_Build_Tools/ 译者地址:[翻]一览新的 Android Gradle 构 ...
- windows安装ffmpeg_免费实用的录屏工具!支持全屏、特定窗口、选定区域录制,支持添加水印、嵌入摄像头(附ffmpeg安装)...
哈喽大家好,我是菌菌~ 在线授课.游戏录制.视频编辑.网上会议--现如今,视频录制非常火爆,一款好用的视频录制工具自然必不可少. 今天,菌菌就给大家分享3款免费又好用的电脑录屏工具,一起来看看吧! w ...
- android 新开发工具,Android开发人员必备的10个开发工具
Android SDK 本身包含很多帮助开发人员设计.开发.测试和发布 Android 应用的工具,在本文中,我们将讨论 10 个最常用的工具. 1. Eclipse ADT Eclipse ADT ...
- 测试android兼容性测试工具,Android兼容性测试工具Spoon
android分布式测试工具. 简介 android众多的版本和机型给android app测试工作带来不小的挑战.Spoon通过将case分布式地执行.将执行结果更友好地展示出来,从而简化andro ...
- android 单位转换工具,Android单位转换工具类
Android单位转换工具类 Android单位转换工具类主要由以下4部分构成 1.这个类不能被初始化 2.dip转px接口 3.sp转px接口 4.px转dip接口 代码如下: import and ...
- android app性能测试工具,Android 性能测试 - 内存
1.内存了解 在Android App的性能优化的各个部分里,内存方面的知识较多且不易理解,内存的问题绝对是最令人头疼的一部分,需要对内存基础知识.内存分配.内存管理机制等非常熟悉,才能排查题. 1. ...
- Android集成开发工具——Android Studio
Android Studio 是谷歌推出的一个Android集成开发工具,基于IntelliJ IDEA. 类似Eclipse ADT,Android Studio 提供了集成的 Android 开发 ...
- android pdf阅读工具,android pdf 阅读器开发, pdf demo, pdf第三方控件
Activity调用的方法 public class PDFActivity extends Activity implements OnPageChangeListener { public sta ...
- android闹钟测试工具,android开发:AlarmManager闹钟管理器的实例
1.AlarmManager,顾名思义,就是"提醒",是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的PendingIntent.通俗点,就是设置一 ...
最新文章
- 【iOS】中间透明的引导蒙层
- 机器学习建模神器PyCaret已开源!提升效率,几行代码轻松搞定模型
- IBM 消费者洞察报告,揭示 5G 娱乐时代的三大关键趋势
- Centos 7.X安装DB2 10.5
- 如何根据指定软件版本制作属于自己的puppet yum源
- GARFIELD@04-30-2005
- spark sql 优化心得
- 计算机系统如何禁止删除文件,电脑禁止安装删除文件 禁止复制电脑文件的方法...
- 杭电1861 游船出租
- Go 语言发布 2018 调查报告,最被诟病问题竟然是......
- 结合源码探讨Android距离传感器亮灭屏机制
- 'net’ 不是内部命令或外部命令,也不是可运行的程序或批处理文件 解决方法...
- Zabbix中文使用手册
- c位边上还有什么位_火箭少女海报一反常态,孟美岐取代yamy站C位,吴宣仪在边上...
- 数据挖掘 / 机器学习——决策树
- 线性代数入门指南:线性方程组
- linux shell 宏定义_一篇教会你写90%的shell脚本
- Equalize the Array(思维)
- Python 小试牛刀
- 小程序 | 小程序中常用的事件 + 事件对象的属性列表 +小程序事件传参 + 小程序全局配置 + 小程序页面配置 + 小程序发起网络数据请求
热门文章
- 数据库期末复习:选择题汇总
- git上传代码的账户名不是本人的问题
- [SinGuLaRiTy] 动态规划题目复习
- 追男妙计 三招搞定!
- java积分管理系统_积分兑换系统_超市积分管理
- 科研方法-X_LAB-方法总结和实践记录
- 2007年春节读书心得
- Https网址在线安全检测网站
- 【安装Oracle 12.2.0.1补丁】Oracle Database SAP Bundle Patch 12.2.0.1.220118 - 202202
- 前端是什么,是干嘛的