现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓6.0以上版本动态权限管理等),把声音录制及播放相关代码做个记录。
public class MediaRecorderActivity extends BaseActivity {private Button start_tv;private ListView listView;//线程操作private ExecutorService mExecutorService;//录音APIprivate 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;//播放音频文件APIprivate MediaPlayer mediaPlayer;//使用Handler更新UI线程private Handler mHandler = new Handler() {@Overridepublic 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;}}};@Overrideprotected void setWindowView() {setContentView(R.layout.activity_record);//录音及播放要使用单线程操作mExecutorService = Executors.newSingleThreadExecutor();dataList = new ArrayList<>();}@Overrideprotected void initViews() {this.start_tv = (Button) findViewById(R.id.start_tv);this.listView = (ListView) findViewById(R.id.listview);}@Overrideprotected void initEvents() {//类似微信等应用按住说话进行录音,所以用OnTouch事件this.start_tv.setOnTouchListener(new View.OnTouchListener() {@Overridepublic 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事件做了处理,返回truereturn true;}});//点击播放对应的录音文件this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic 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() {@Overridepublic 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);//设置保存文件格式为MP4mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//设置采样频率,44100是所有安卓设备都支持的频率,频率越高,音质越好,当然文件越大mMediaRecorder.setAudioSamplingRate(44100);//设置声音数据编码格式,音频通用格式是AACmMediaRecorder.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);//录音成功,发MessagemHandler.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;}}@Overridepublic void onClick(View view) {}@Overrideprotected 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();}}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onCompletion(MediaPlayer mediaPlayer) {//播放完成playEndOrFail(true);}});//播放发生错误监听事件mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic 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;}}}
页面布局
<LinearLayoutxmlns: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"><Buttonandroid:id="@+id/start_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="开始录音"android:textSize="16sp"/><ListViewandroid: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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。