根据工作需要自己写的实现录音,试听,保存及上传的音频播放器:
public ImageView mBtnRecord; public LinearLayout activity_record_video_send; public LinearLayout activity_record_video_paly; public LinearLayout activity_record_vedio_again; public LinearLayout activity_record_ll; public TextView mTime; public TextView activity_recording_show; public TextView activity_record_time_tv; private AnimatedRecordingView mArvView; private boolean isRecording; private boolean isStart; private int timeCount; final int TIME_COUNT = 0x101; private RecordDaoImpl mDao; //录音文件保存路径 private File myRecAudioDir; //合成的录音文件 private File myFinalFile; //SDka存在 private boolean mSDCardExit; //记录需要合成的amr音频文件 private ArrayList<String> mTempList; //计时器 private Timer timer = null; private TimerTask timeTask = null; //暂停状态 private boolean inPause; // private String finish @Override public void recorderStart() { } @Override public void recorderStop() { } @Override public void volumeChange(float vol) { mArvView.setVolume(vol); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RecorderHelper.getInstance().setRecorderListener(this); mDao = new RecordDaoImpl(this); EventBus.getDefault().register(this); // 判断sd Card是否插入 mSDCardExit = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); mTempList = new ArrayList<String>(); initView(); initEvent(); } private void initView() { setContentView(R.layout.activity_record_video); activity_record_video_paly = (LinearLayout) findViewById(R.id.activity_record_video_paly); activity_record_vedio_again = (LinearLayout) findViewById(R.id.activity_record_vedio_again); activity_record_ll = (LinearLayout) findViewById(R.id.activity_record_ll); mBtnRecord = (ImageView) findViewById(R.id.btn_record); activity_record_video_send = (LinearLayout) findViewById(R.id.activity_record_video_send); mTime = (TextView) findViewById(R.id.text_time); activity_recording_show = (TextView) findViewById(R.id.activity_recording_show); activity_record_time_tv = (TextView) findViewById(R.id.activity_record_time_tv); mArvView = (AnimatedRecordingView) findViewById(R.id.activity_record_wave); ((TextView) findViewById(R.id.layout_daohanglan_title)).setText("录音"); } private void initEvent() { activity_record_video_send.setOnClickListener(this); mBtnRecord.setOnClickListener(this); activity_record_video_paly.setOnClickListener(this); activity_record_vedio_again.setOnClickListener(this); ((ImageView) findViewById(R.id.layout_daohanglan_fanhui)).setOnClickListener(this); } @Override protected void onResume() { super.onResume(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.layout_daohanglan_fanhui: finish(); break; case R.id.activity_record_video_paly: if (inPause) { Intent intent = new Intent(this, TestListeningActivity.class); intent.putExtra("countTime", timeCount); startActivity(intent); } else { Toast.makeText(RecordVideoActivity.this, "请停止录制课程之后再进行试听", Toast.LENGTH_SHORT).show(); } break; case R.id.activity_record_vedio_again: if (isStart) { if (inPause) { recordAgain(); } else { Toast.makeText(RecordVideoActivity.this, "请停止录制课程之后再重新录制", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(RecordVideoActivity.this, "请录音之后再试听", Toast.LENGTH_SHORT).show(); } break; case R.id.activity_record_video_send: //这里写暂停处理的 文件!加上list里面 语音合成起来 if (inPause) { //在暂停状态按下结束键,处理list就可以了 PreferenceUtil.setPreferenceInt(this, "TotalRecordTime", timeCount); getInputCollection(mTempList); //还原标志位 isStart = false; inPause = false; isRecording = false; timeCount = 0; mTime.setText("00:00"); activity_recording_show.setVisibility(View.GONE); activity_record_time_tv.setVisibility(View.VISIBLE); activity_record_ll.setVisibility(View.GONE); Intent intent = new Intent(RecordVideoActivity.this, RecordCourseListActivity.class); intent.putExtra("filepath", myFinalFile.getAbsolutePath()); startActivity(intent); } else { Toast.makeText(RecordVideoActivity.this, "请停止录制课程之后再进行上传", Toast.LENGTH_SHORT).show(); return; } // postToOss(); break; case R.id.btn_record: // TODO: 2017/9/25 0025 添加录音逻辑的判断及异常处理 每次录音检查权限 requestPermission(Manifest.permission.RECORD_AUDIO, Configuration.RECORD_AUDIO); if (isStart) { //已经暂停过了,再次点击按钮 开始录音,录音状态在录音中 if (inPause) { RecorderHelper.getInstance().startRecord(); mArvView.start(); inPause = false; isRecording = true; activity_recording_show.setVisibility(View.VISIBLE); activity_recording_show.setText("麦克风录制中"); startTime(); } //正在录音,点击暂停,现在录音状态为暂停 else { //当前正在录音的文件名全称 mTempList.add(RecorderHelper.getInstance().getFilePath()); inPause = true; isRecording = false; mArvView.stop(); stopRecord(); activity_recording_show.setVisibility(View.VISIBLE); activity_recording_show.setText("录音已暂停"); stopTime(); // RecorderHelper.getInstance().cancel(); } } else { if (mTempList != null) { mTempList.clear(); } if (!mSDCardExit) { Toast.makeText(RecordVideoActivity.this, "请插入SD card", Toast.LENGTH_LONG).show(); return; } RecorderHelper.getInstance().startRecord(); activity_recording_show.setVisibility(View.VISIBLE); activity_recording_show.setText("麦克风录制中"); activity_record_time_tv.setVisibility(View.GONE); activity_record_ll.setVisibility(View.VISIBLE); mArvView.start(); isStart = true; startTime(); isRecording = true; } break; } } public void recordAgain() { DialogUtil.showDialog(this, 0, "温馨提示", "是否确定重新录制", "确定", "取消", new DialogUtil.DialogCallback() { @Override protected void onCancel(DialogInterface dialog) { super.onCancel(dialog); } @Override public void onOk(DialogInterface dialog) { dialog.dismiss(); deleteListRecord(); isStart = false; inPause = false; isRecording = false; timeCount = 0; mTime.setText("00:00"); activity_recording_show.setVisibility(View.GONE); activity_record_time_tv.setVisibility(View.VISIBLE); activity_record_ll.setVisibility(View.GONE); } }); } public void startTime() { if (timer == null) { timer = new Timer(); } if (timeTask == null) { timeTask = new TimerTask() { public void run() { timeCount++; timeCount(); } }; } if (timer != null && timeTask != null) { timer.schedule(timeTask, 0, 1000); } } public void stopTime() { if (timer != null) { timer.cancel(); timer = null; } if (timeTask != null) { timeTask.cancel(); timeTask = null; } } /** * @return 将合并的流用字符保存 */ public void getInputCollection(ArrayList<String> list) { if (mSDCardExit) { String pathStr = FileUtil.getAudioRecordFilePath(); myRecAudioDir = new File(pathStr); if (!myRecAudioDir.exists()) { myRecAudioDir.mkdirs(); Log.v("录音", "创建录音文件!" + myRecAudioDir.exists()); } } RecordFile filerecord = new RecordFile(); String mMinute1 = getTime(); // 创建音频文件,合并的文件放这里 myFinalFile = new File(myRecAudioDir, mMinute1 + Contact.AMR_NB); if (!myFinalFile.exists()) { try { myFinalFile.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(myFinalFile); } catch (FileNotFoundException e) { e.printStackTrace(); } //list里面为暂停录音 所产生的 几段录音文件的名字,中间几段文件的减去前面的6个字节头文件 for (int i = 0; i < list.size(); i++) { File file = new File(list.get(i)); Log.d("list的长度", list.size() + ""); try { FileInputStream fileInputStream = new FileInputStream(file); byte[] myByte = new byte[fileInputStream.available()]; //文件长度 int length = myByte.length; //头文件 if (i == 0) { while (fileInputStream.read(myByte) != -1) { fileOutputStream.write(myByte, 0, length); } } else { while (fileInputStream.read(myByte) != -1) { fileOutputStream.write(myByte, 6, length - 6); } } fileOutputStream.flush(); fileInputStream.close(); System.out.println("合成文件长度:" + myFinalFile.length()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //结束后关闭流 try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } filerecord.setCreateTime(mMinute1); filerecord.setShowTime(mTime.getText().toString().trim()); filerecord.setFilePath(myFinalFile.getAbsolutePath()); String size = FileUtil.FormetFileSize(myFinalFile.length()); filerecord.setFileSize(size); filerecord.setTimeCount(timeCount); mDao.add(filerecord); //合成一个文件后,删除之前暂停录音所保存的零碎合成文件 deleteListRecord(); // adapter.add(file1.getName()); } private void deleteListRecord() { for (int i = 0; i < mTempList.size(); i++) { File file = new File((String) mTempList.get(i)); if (file.exists()) { file.delete(); } } //正在暂停后,继续录音的这一段音频文件 // if (isAddLastRecord) { // myRecAudioFile.delete(); // } } private String getTime() { SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日HH-mm-ss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String createData = formatter.format(curDate); long data = curDate.getTime(); System.out.println("当前时间"); return createData; } @Subscribe(threadMode = ThreadMode.MAIN) public void recAgain(RecordAgain event) { deleteListRecord(); isStart = false; inPause = false; isRecording = false; timeCount = 0; mTime.setText("00:00"); activity_recording_show.setVisibility(View.GONE); activity_record_time_tv.setVisibility(View.VISIBLE); activity_record_ll.setVisibility(View.GONE); } @Override protected void onPause() { super.onPause(); // RecorderHelper.getInstance().cancel(); } private void stopRecord() { RecorderHelper.getInstance().cancel(); mArvView.stop(); // } } Runnable mLoading = new Runnable() { @Override public void run() { mArvView.stop(); } }; public static String FormatMiss(int miss) { String hh = miss / 3600 > 9 ? miss / 3600 + "" : "0" + miss / 3600; String mm = (miss % 3600) / 60 > 9 ? (miss % 3600) / 60 + "" : "0" + (miss % 3600) / 60; String ss = (miss % 3600) % 60 > 9 ? (miss % 3600) % 60 + "" : "0" + (miss % 3600) % 60; return hh + ":" + mm + ":" + ss; } Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case TIME_COUNT: int count = (int) msg.obj; Log.e("mainActivity", "count == " + count); mTime.setText(FormatMiss(count)); break; } } }; public void timeCount() { Message msg = Message.obtain(); msg.what = TIME_COUNT; msg.obj = timeCount; myHandler.sendMessage(msg); } @Override protected void onDestroy() { super.onDestroy(); myHandler.removeCallbacksAndMessages(null); stopTime(); EventBus.getDefault().unregister(this); } public void requestPermission(String permission,int requestCode){ PermissionUtils.REQUEST_CODE_PERMISSION = requestCode; boolean checkPermission = PermissionUtils.checkPermission(this,permission,requestCode); if (checkPermission){ permissionSuccess(PermissionUtils.REQUEST_CODE_PERMISSION); } } private void permissionSuccess(int requestCode) { LogUtil.d("recordvideoactivity", "获取权限成功=" + requestCode); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PermissionUtils.REQUEST_CODE_PERMISSION){ if (PermissionUtils.verifyPermissions(grantResults)){ permissionSuccess(PermissionUtils.REQUEST_CODE_PERMISSION); }else{ permissionFail(PermissionUtils.REQUEST_CODE_PERMISSION); } } } /** * 权限获取失败 * * @param requestCode */ public void permissionFail(int requestCode) { LogUtil.d("recordvideoactivity", "获取权限失败=" + requestCode); }
录音帮助类:
public class RecorderHelper { private static final String TAG = "RecorderHelper"; String PATH; // static final int MAX_RECORDER_TIME = 3000; private int BASE = 1; private int SPACE = 20;// 间隔取样时间 private MediaRecorder mMediaRecorder; private static volatile RecorderHelper sInst = null; onRecorderListener mListener; Handler mHandler = new Handler(); public File myRecAudioFile; //录音文件保存路径 private File myRecAudioDir; //文件存在 private boolean mSDCardExit; public static RecorderHelper getInstance() { RecorderHelper inst = sInst; if (inst == null) { synchronized (RecorderHelper.class) { inst = sInst; if (inst == null) { inst = new RecorderHelper(); sInst = inst; } } } return inst; } public RecorderHelper setPath(String path) { this.PATH = path; return this; } private RecorderHelper() { } public void startRecord() { // 判断sd Card是否插入 mSDCardExit = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); // 取得sd card路径作为录音文件的位置 if (mSDCardExit) { String pathStr = FileUtil.getAudioRecordFilePath(); myRecAudioDir = new File(pathStr); if (!myRecAudioDir.exists()) { myRecAudioDir.mkdirs(); Log.v("录音", "创建录音文件!" + myRecAudioDir.exists()); } } String mMinute1 = FileUtil.getTime(); myRecAudioFile = new File(myRecAudioDir, mMinute1 + Contact.AMR_NB); if (!myRecAudioFile.exists()) { try { myRecAudioFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { mMediaRecorder = new MediaRecorder(); // 设置录音文件的保存位置 LogUtil.e("recoderVideoActivitypATH", myRecAudioFile.getAbsolutePath()); LogUtil.e("recoderVideoActivitypATH", myRecAudioFile.getPath()); // 设置录音的来源(从哪里录音) mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置录音的保存格式 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR); // 设置录音的编码 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setOutputFile(myRecAudioFile.getAbsolutePath()); mMediaRecorder.prepare(); mMediaRecorder.start(); updateMicStatus(); } catch (Exception e) { e.printStackTrace(); } } public void playSound() { if (!myRecAudioFile.exists()) { Toast.makeText(MyApplication.getmContext(), "无音频文件", Toast.LENGTH_SHORT).show(); return; } MediaPlayer mediaPlayer; if (myRecAudioFile.length() <= 0) { Toast.makeText(MyApplication.getmContext(), "录音权限已被禁止,请前往设置中心添加录音权限", Toast.LENGTH_SHORT).show(); return; } try { Uri uri = Uri.fromFile(myRecAudioFile); mediaPlayer = MediaPlayer.create(MyApplication.getmContext(), uri); mediaPlayer.start(); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Toast.makeText(MyApplication.getmContext(), "播放完成", Toast.LENGTH_SHORT).show(); EventBus.getDefault().post(new PlayFinish()); } }); } catch (Exception e) { e.printStackTrace(); } } public void stopAndRelease() { if (null != mMediaRecorder) { mMediaRecorder.stop(); mMediaRecorder.release(); mMediaRecorder = null; } if (myRecAudioFile.length() <= 0) { Toast.makeText(MyApplication.getmContext(), "录音失败,录音权限已被禁止,请前往设置中心添加录音权限", Toast.LENGTH_SHORT).show(); return; } } public void setRecorderListener(onRecorderListener listener) { this.mListener = listener; } public void cancel() { mHandler.removeCallbacks(mUpdateMicStatusTimer, SPACE); stopAndRelease(); } public String getFilePath() { if (myRecAudioFile != null && myRecAudioFile.exists()) { return myRecAudioFile.getAbsolutePath(); } return ""; } public interface onRecorderListener { void recorderStart(); void recorderStop(); void volumeChange(float vol); } private void updateMicStatus() { if (mMediaRecorder != null) { double ratio = (double) mMediaRecorder.getMaxAmplitude() / BASE; double db = 0;// 分贝 if (ratio > 1) { db = 20 * Math.log10(ratio); } if (null != mListener) { mListener.volumeChange((float) db); } mHandler.postDelayed(mUpdateMicStatusTimer, SPACE); } } private Runnable mUpdateMicStatusTimer = new Runnable() { public void run() { updateMicStatus(); } }; // private Runnable mTimeOut = new Runnable() { // @Override // public void run() { // cancel(); // } // }; }