Android使用MediaRecorder实现录音及播放

现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓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

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

(0)

相关推荐

  • Android录音播放管理工具

    1.语音播放直接用系统工具就好了,这个就不多说了,根据传入的路径(网络路径或本地路径均可)播放音频文件 /** * Created by zhb on 2017/1/16. * 音乐在线播放 */ public class PlayManager { private Context mcontext; public PlayManager(Context context){ this.mcontext = context; } public void play(String song){ Med

  • Android编程开发录音和播放录音简单示例

    本文实例讲述了Android编程开发录音和播放录音的方法.分享给大家供大家参考,具体如下: /* * The application needs to have the permission to write to external storage * if the output file is written to the external storage, and also the * permission to record audio. These permissions must be

  • Android 录音与播放功能的简单实例

     Android 录音与播放功能的简单实例 最近在研究Android中一些常用的功能,像地图.拍照.录音和播放的实现等等,还有一些侧滑.动画等是如何实现的. 今天就把录音和播放的实现分享一下,录音和播放比较简单,利用android内部的类即可实现. 1.先看下运行后的界面: 以下三张图分别是进入.录音.播放时的. 2.Layout布局文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout

  • Android实现自制和播放录音程序

    首先,让我们先看下实现的截图: 当有录音文件存在时,会显示在下面的ListView当中. 下面给出实现的完整代码: 1.主程序代码 package irdc.ex07_11; import java.io.File; import java.io.IOException; import java.util.ArrayList; import android.app.Activity; import android.content.Intent; import android.media.Medi

  • Android使用MediaRecorder实现录音及播放

    现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓6.0以上版本动态权限管理等),把声音录制及播放相关代码做个记录. public class MediaRecorderActivity extends BaseActivity { private Button start_tv; private ListView listView; //线程操作 private ExecutorService mExecutorService; //录音API pri

  • Android一个类实现录音与播放实例

    目录 前言 实现效果 代码实现 XML 静态权限 动态权限 总结 前言 最近混合开发的项目 在做语音识别时 h5拿不到麦克风的权限几经周折 开发任务又落到了原生开发这里 先写一个demo实现录音和播放功能 然后由web端同事调用交互方法 实现效果 代码实现 public class MainActivity extends AppCompatActivity { private static final String LOG_TAG = "MainActivity"; //语音文件保存

  • Android编程检测手机录音权限是否打开的方法

    本文实例讲述了Android编程检测手机录音权限是否打开的方法.分享给大家供大家参考,具体如下: 6.0之前的权限检测只是检测到是否在清单文件中注册 Boolean flag = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.RECORD_AUDIO", "包名")); Boolean flag = PermissionChecker.checkSelfPer

  • Android简单的利用MediaRecorder进行录音的实例代码

    复制代码 代码如下: package com.ppmeet; import java.io.IOException; import android.app.Activity;  import android.graphics.PixelFormat;  import android.media.MediaRecorder;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClick

  • android 通过MediaRecorder实现简单的录音示例

    整理文档,搜刮出一个android 通过MediaRecorder实现简单的录音示例,稍微整理精简一下做下分享. MainActivity package com.centaur.collectvoice; import android.media.MediaRecorder; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; impo

  • Android仿微信录音功能(录音后的raw文件转mp3文件)

    现在很多时候需要用到录音,然后如果我们的App是ios和android两端的话,就要考虑录音的文件在两端都能使用,这个时候就需要适配,两端的录音文件都要是mp3文件,这样才能保证两边都能播放. 针对这个,封装了一个简单可用的录音控件. 使用方法: 1.在xml文件中添加 <ant.muxi.com.audiodemo.view.SoundTextView android:id="@+id/record_audio" android:text="按住开始录音"

  • Android用AudioRecord进行录音

    在音视频开发中,录音当然是必不可少的.首先我们要学会单独的录音功能,当然这里说的录音是指用AudioRecord来录音,读取录音原始数据,读到的就是所谓的PCM数据.对于录音来说,最重要的几个参数要搞明白: 1.simpleRate采样率,采样率就是采样频率,每秒钟记录多少个样本. 2.channelConfig通道配置,其实就是所谓的单通道,双通道之类的,AudioFormat.CHANNEL_IN_MONO单通道,AudioFormat.CHANNEL_IN_STEREO双通道,这里只列了这

  • Android使用Flutter实现录音插件

    目录 安卓部分 手动注册 Android和Dart的通讯 安卓录音 Dart module部分 iOS部分 手动注册插件 iOS插件 Dart调用部分 原生提供功能,Dart module 通过 method channel 异步调用 安卓部分 手动注册 Flutter 官方的做法,就是自动注册插件, 很方便 手动注册,体现本文的不同 插件是 AudioRecorderPlugin class MainActivity: FlutterActivity() { override fun onCr

  • android编程实现电话录音的方法

    本文实例讲述了android编程实现电话录音的方法.分享给大家供大家参考.具体如下: 在清单文件AndroidManifest.xml中添加权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUN

随机推荐