中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android怎樣實現錄屏小功能

發布時間:2021-09-27 11:28:22 來源:億速云 閱讀:130 作者:小新 欄目:編程語言

這篇文章主要為大家展示了“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<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;  }  @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<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怎樣實現錄屏小功能”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

惠州市| 邵武市| 大同县| 交口县| 滨州市| 廊坊市| 北辰区| 敦煌市| 扎兰屯市| 交口县| 乐亭县| 新邵县| 托克逊县| 龙泉市| 建阳市| 常州市| 三台县| 祥云县| 遂平县| 盐津县| 陆良县| 玉树县| 沧州市| 乌拉特后旗| 龙江县| 启东市| 乌兰浩特市| 北碚区| 周至县| 岳西县| 砀山县| 临江市| 广平县| 盐边县| 镇赉县| 新疆| 中阳县| 正宁县| 余江县| 巴楚县| 衡阳县|