本文实例为大家分享了android实现录屏小功能的具体代码,供大家参考,具体内容如下

思路

android实现录屏功能有两种方案,一种是直接使用android自带的MediaProjectionManager实现录屏功能,第二种是是只录语音,用户的操作通过某种方式进行记录保存,最后通过某种协议进行播放。

两种方案各有各的优缺点,前者实现方式简单,但无法只录制特定区域的画面,并且生成的视频文件一般都比较大。后者实现较为繁琐,音频录制android7.0之前没有暂停方法,只能生成多个文件,然后对音频进行合成。用户的操作需要自己进行保存,播放时还原。播放器需要自定义生成。但后者的好处是可扩展性高,支持特定区域录制,并且生成的音频文件比较小。

需求

录制画板,画板要求可以更改颜色粗细,可以擦除。画板底部可以是白板,图片。图片要求是相机拍摄或者本地图片。可以播放录制内容;需要上传,所以文件要小,所有只能选择第二种方式。
github地址

android实现录屏小功能_第1张图片

整个项目生成的是一个文件夹,文件夹中包含一个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 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();        }      }    }  }

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

更多相关文章

  1. Android将手机相册图片展示到GridView中
  2. Android 数据缓存-文件存储
  3. Android webview 实现h5中调用原生系统相册/相机并进行图片压缩
  4. Android 开发之深入分析布局文件&又是“Hello World!”
  5. android app 浅谈文件上传(图片和文件)
  6. 转载:Android中对Log日志文件的分析
  7. Android显示图片避免OOM和ANR小结
  8. 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHtt
  9. 一步一步学Android ROM开发(一)——修改现有ROM资源文件

随机推荐

  1. Android(安卓)隐式调用 intent
  2. 如何在win7下安装和配置Android(安卓)Stu
  3. Android(安卓)自定义 spinner (背景、字
  4. Android(安卓)“Not granting permission
  5. android获取当前文字的总体长度的方法
  6. android源码下载,从Android2.2.2到4.2.2的
  7. android Sqlite多线程访问异常解决方案
  8. Activity横竖屏切换
  9. Android实现图片帮助跳转以及选择重拍Sql
  10. android 发送短信