溫馨提示×

溫馨提示×

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

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

android怎樣實現(xiàn)錄屏小功能

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

這篇文章主要為大家展示了“android怎樣實現(xiàn)錄屏小功能”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“android怎樣實現(xiàn)錄屏小功能”這篇文章吧。

思路

android實現(xiàn)錄屏功能有兩種方案,一種是直接使用android自帶的MediaProjectionManager實現(xiàn)錄屏功能,第二種是是只錄語音,用戶的操作通過某種方式進行記錄保存,最后通過某種協(xié)議進行播放。

兩種方案各有各的優(yōu)缺點,前者實現(xiàn)方式簡單,但無法只錄制特定區(qū)域的畫面,并且生成的視頻文件一般都比較大。后者實現(xiàn)較為繁瑣,音頻錄制android7.0之前沒有暫停方法,只能生成多個文件,然后對音頻進行合成。用戶的操作需要自己進行保存,播放時還原。播放器需要自定義生成。但后者的好處是可擴展性高,支持特定區(qū)域錄制,并且生成的音頻文件比較小。

需求

錄制畫板,畫板要求可以更改顏色粗細(xì),可以擦除。畫板底部可以是白板,圖片。圖片要求是相機拍攝或者本地圖片??梢圆シ配浿苾?nèi)容;需要上傳,所以文件要小,所有只能選擇第二種方式。github地址

整個項目生成的是一個文件夾,文件夾中包含一個MP3文件,一個cw協(xié)議文件(存儲用戶的操作),圖片。整個畫板是一個recyclerView,item中包含一個涂鴉畫板,圖片控件。播放時讀取cw協(xié)議文件,按照時間一個個繪制,協(xié)議內(nèi)容包含畫板各個頁的內(nèi)容是空白畫板還是圖片,時間點,操作(切換圖片/畫線)。

音頻

//開始錄音  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個字節(jié)的頭信息    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);

獲得當(dāng)前是第幾頁,類似viewPage的pageSelect

public class RecyclerViewPageChangeListenerHelper extends RecyclerView.OnScrollListener {  private SnapHelper snapHelper;  private OnPageChangeListener onPageChangeListener;  private int oldPosition = -1;//防止同一Position多次觸發(fā)  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();    //獲取當(dāng)前選中的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 當(dāng)滾動停止時觸發(fā)防止在滾動過程中不停觸發(fā)      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);  }}

獲得當(dāng)前選擇的item(只能獲得可視頁面item)

View view = forbitLayoutManager.findViewByPosition(position);  //有時會獲取到null,是因為頁面還沒有渲染完成,可以使用  recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver        .OnGlobalLayoutListener() {      @Override      public void onGlobalLayout() {       //會多次調(diào)用,執(zhí)行完邏輯之后取消監(jiān)聽          recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);      }    });

根據(jù)時間進行播放

private void convertCWACT(CW cw, int seconds,boolean isSeek) {    List<CWACT> cwacts = cw.getACT();    //如何是播放器跳轉(zhuǎn),先回到首頁,清空所有item中的畫板,防止從高時間跳轉(zhuǎn)到低時間出現(xiàn)錯誤    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怎樣實現(xiàn)錄屏小功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI