Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android使用MediaRecorder實現錄音及播放

Android使用MediaRecorder實現錄音及播放

編輯:關於Android編程

現在項目中有使用到音視頻相關技術,在參考了網上各種大牛的資料及根據自己項目實際情況(兼容安卓6.0以上版本動態權限管理等),把聲音錄制及播放相關代碼做個記錄。

public class MediaRecorderActivity extends BaseActivity {
  private Button start_tv;
  private ListView listView;
  //線程操作
  private ExecutorService mExecutorService;
  //錄音API
  private MediaRecorder mMediaRecorder;
  //錄音開始時間與結束時間
  private long startTime, endTime;
  //錄音所保存的文件
  private File mAudioFile;
  //文件列表數據
  private List<FileBean> dataList;
  //錄音文件數據列表適配器
  private AudioAdapter mAudioAdapter;
  //錄音文件保存位置
  private String mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/audio/";
  //當前是否正在播放
  private volatile boolean isPlaying;
  //播放音頻文件API
  private MediaPlayer mediaPlayer;
  //使用Handler更新UI線程
  private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
      switch (msg.what) {
        case Constant.RECORD_SUCCESS:
          //錄音成功,展示數據
          if (null == mAudioAdapter) {
            mAudioAdapter = new AudioAdapter(MediaRecorderActivity.this, dataList, R.layout.file_item_layout);
          }
          listView.setAdapter(mAudioAdapter);
          break;
        //錄音失敗
        case Constant.RECORD_FAIL:
          showToastMsg(getString(R.string.record_fail));
          break;
        //錄音時間太短
        case Constant.RECORD_TOO_SHORT:
          showToastMsg(getString(R.string.time_too_short));
          break;
        case Constant.PLAY_COMPLETION:
          showToastMsg(getString(R.string.play_over));
          break;
        case Constant.PLAY_ERROR:
          showToastMsg(getString(R.string.play_error));
          break;

      }
    }
  };

  @Override
  protected void setWindowView() {
    setContentView(R.layout.activity_record);
    //錄音及播放要使用單線程操作
    mExecutorService = Executors.newSingleThreadExecutor();
    dataList = new ArrayList<>();
  }

  @Override
  protected void initViews() {
    this.start_tv = (Button) findViewById(R.id.start_tv);
    this.listView = (ListView) findViewById(R.id.listview);
  }

  @Override
  protected void initEvents() {
    //類似微信等應用按住說話進行錄音,所以用OnTouch事件
    this.start_tv.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (motionEvent.getAction()) {
          //按下操作
          case MotionEvent.ACTION_DOWN:
            //安卓6.0以上錄音相應權限處理
            if (Build.VERSION.SDK_INT > 22) {
              permissionForM();
            } else {
              startRecord();
            }
            break;
          //松開操作
          case MotionEvent.ACTION_CANCEL:
          case MotionEvent.ACTION_UP:
            stopRecord();
            break;
        }
        //對OnTouch事件做了處理,返回true
        return true;
      }
    });
    //點擊播放對應的錄音文件
    this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        //使用MediaPlayer播放聲音文件
        startPlay(dataList.get(i).getFile());
      }
    });
  }


  /**
   * @description 開始進行錄音
   * @author ldm
   * @time 2017/2/9 9:18
   */
  private void startRecord() {
    start_tv.setText(R.string.stop_by_up);
    start_tv.setBackgroundResource(R.drawable.bg_gray_round);
    //異步任務執行錄音操作
    mExecutorService.submit(new Runnable() {
      @Override
      public void run() {
        //播放前釋放資源
        releaseRecorder();
        //執行錄音操作
        recordOperation();
      }
    });
  }

  /**
   * @description 錄音失敗處理
   * @author ldm
   * @time 2017/2/9 9:35
   */
  private void recordFail() {
    mAudioFile = null;
    mHandler.sendEmptyMessage(Constant.RECORD_FAIL);
  }

  /**
   * @description 錄音操作
   * @author ldm
   * @time 2017/2/9 9:34
   */
  private void recordOperation() {
    //創建MediaRecorder對象
    mMediaRecorder = new MediaRecorder();
    //創建錄音文件,.m4a為MPEG-4音頻標准的文件的擴展名
    mAudioFile = new File(mFilePath + System.currentTimeMillis() + ".m4a");
    //創建父文件夾
    mAudioFile.getParentFile().mkdirs();
    try {
      //創建文件
      mAudioFile.createNewFile();
      //配置mMediaRecorder相應參數
      //從麥克風采集聲音數據
      mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      //設置保存文件格式為MP4
      mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
      //設置采樣頻率,44100是所有安卓設備都支持的頻率,頻率越高,音質越好,當然文件越大
      mMediaRecorder.setAudioSamplingRate(44100);
      //設置聲音數據編碼格式,音頻通用格式是AAC
      mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
      //設置編碼頻率
      mMediaRecorder.setAudioEncodingBitRate(96000);
      //設置錄音保存的文件
      mMediaRecorder.setOutputFile(mAudioFile.getAbsolutePath());
      //開始錄音
      mMediaRecorder.prepare();
      mMediaRecorder.start();
      //記錄開始錄音時間
      startTime = System.currentTimeMillis();
    } catch (Exception e) {
      e.printStackTrace();
      recordFail();
    }
  }


  /**
   * @description 結束錄音操作
   * @author ldm
   * @time 2017/2/9 9:18
   */
  private void stopRecord() {
    start_tv.setText(R.string.speak_by_press);
    start_tv.setBackgroundResource(R.drawable.bg_white_round);
    //停止錄音
    mMediaRecorder.stop();
    //記錄停止時間
    endTime = System.currentTimeMillis();
    //錄音時間處理,比如只有大於2秒的錄音才算成功
    int time = (int) ((endTime - startTime) / 1000);
    if (time >= 3) {
      //錄音成功,添加數據
      FileBean bean = new FileBean();
      bean.setFile(mAudioFile);
      bean.setFileLength(time);
      dataList.add(bean);
      //錄音成功,發Message
      mHandler.sendEmptyMessage(Constant.RECORD_SUCCESS);
    } else {
      mAudioFile = null;
      mHandler.sendEmptyMessage(Constant.RECORD_TOO_SHORT);
    }
    //錄音完成釋放資源
    releaseRecorder();
  }

  /**
   * @description 翻放錄音相關資源
   * @author ldm
   * @time 2017/2/9 9:33
   */
  private void releaseRecorder() {
    if (null != mMediaRecorder) {
      mMediaRecorder.release();
      mMediaRecorder = null;
    }
  }

  @Override
  public void onClick(View view) {

  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    //頁面銷毀,線程要關閉
    mExecutorService.shutdownNow();
  }
  /*******6.0以上版本手機權限處理***************************/
  /**
   * @description 兼容手機6.0權限管理
   * @author ldm
   * @time 2016/5/24 14:59
   */
  private void permissionForM() {
    if (ContextCompat.checkSelfPermission(this,
        Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

      ActivityCompat.requestPermissions(this,
          new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE},
          Constant.PERMISSIONS_REQUEST_FOR_AUDIO);
    } else {
      startRecord();
    }

  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                      @NonNull String[] permissions, @NonNull int[] grantResults) {

    if (requestCode == Constant.PERMISSIONS_REQUEST_FOR_AUDIO) {
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        startRecord();
      }
      return;
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

  /**
   * @description 播放音頻
   * @author ldm
   * @time 2017/2/9 16:54
   */
  private void playAudio(final File mFile) {
    if (null != mFile && !isPlaying) {
      isPlaying = true;
      mExecutorService.submit(new Runnable() {
        @Override
        public void run() {
          startPlay(mFile);
        }
      });
    }
  }

  /**
   * @description 開始播放音頻文件
   * @author ldm
   * @time 2017/2/9 16:56
   */
  private void startPlay(File mFile) {
    try {
      //初始化播放器
      mediaPlayer = new MediaPlayer();
      //設置播放音頻數據文件
      mediaPlayer.setDataSource(mFile.getAbsolutePath());
      //設置播放監聽事件
      mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
          //播放完成
          playEndOrFail(true);
        }
      });
      //播放發生錯誤監聽事件
      mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
          playEndOrFail(false);
          return true;
        }
      });
      //播放器音量配置
      mediaPlayer.setVolume(1, 1);
      //是否循環播放
      mediaPlayer.setLooping(false);
      //准備及播放
      mediaPlayer.prepare();
      mediaPlayer.start();
    } catch (IOException e) {
      e.printStackTrace();
      //播放失敗正理
      playEndOrFail(false);
    }

  }

  /**
   * @description 停止播放或播放失敗處理
   * @author ldm
   * @time 2017/2/9 16:58
   */
  private void playEndOrFail(boolean isEnd) {
    isPlaying = false;
    if (isEnd) {
      mHandler.sendEmptyMessage(Constant.PLAY_COMPLETION);
    } else {
      mHandler.sendEmptyMessage(Constant.PLAY_ERROR);
    }
    if (null != mediaPlayer) {
      mediaPlayer.setOnCompletionListener(null);
      mediaPlayer.setOnErrorListener(null);
      mediaPlayer.stop();
      mediaPlayer.reset();
      mediaPlayer.release();
      mediaPlayer = null;
    }
  }
}

頁面布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin">

  <Button
      android:id="@+id/start_tv"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="開始錄音"
      android:textSize="16sp"
      />

  <ListView
      android:id="@+id/listview"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:divider="#d1d1d1"
      android:dividerHeight="1dp"
      android:scrollbars="none"
      android:layout_marginTop="10dp"
      android:layout_marginBottom="10dp"></ListView>

</LinearLayout>

對應資源文件strings.xml:

<resources>
  <string name="app_name">mediarecorder</string>
  <string name="record_fail">錄音失敗</string>
  <string name="time_too_short">時間太短,請重新錄音</string>
  <string name="play_over">播放完成</string>
  <string name="play_error">抱歉,播放發生異常</string>
  <string name="stop_by_up">松開停止錄音</string>
  <string name="speak_by_press">按住說話</string>
  <string name="start_record">開始錄音</string>
  <string name="stop_record">停止錄音</string>
</resources>

錄音相關權限 :

<!--SD卡權限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--錄音權限-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>


安卓錄制播放音頻:https://github.com/ldm520/Android_Media

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved