最近有小伙伴經常android的錄音怎么實現,有沒有相關的案例。今天給大家推薦一個android中實現錄音和播放的小案例。
效果圖:
一、實現錄音的 Service 關鍵代碼:
// 開始錄音 public void startRecording() { setFileNameAndPath(); mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //錄音文件保存的格式,這里保存為 mp4 mRecorder.setOutputFile(mFilePath); // 設置錄音文件的保存路徑 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mRecorder.setAudioChannels(1); // 設置錄音文件的清晰度 mRecorder.setAudioSamplingRate(44100); mRecorder.setAudioEncodingBitRate(192000); try { mRecorder.prepare(); mRecorder.start(); mStartingTimeMillis = System.currentTimeMillis(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } } // 設置錄音文件的名字和保存路徑 public void setFileNameAndPath() { File f; do { count++; mFileName = getString(R.string.default_file_name) + "_" + (System.currentTimeMillis()) + ".mp4"; mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath(); mFilePath += "/SoundRecorder/" + mFileName; f = new File(mFilePath); } while (f.exists() && !f.isDirectory()); } // 停止錄音 public void stopRecording() { mRecorder.stop(); mElapsedMillis = (System.currentTimeMillis() - mStartingTimeMillis); mRecorder.release(); getSharedPreferences("sp_name_audio", MODE_PRIVATE) .edit() .putString("audio_path", mFilePath) .putLong("elpased", mElapsedMillis) .apply(); if (mIncrementTimerTask != null) { mIncrementTimerTask.cancel(); mIncrementTimerTask = null; } mRecorder = null; }
二、顯示錄音界面的 RecordAudioDialogFragment
用戶進行的時候,總不能讓 App 跳轉到另外一個界面吧,這樣用戶體驗並不是很好,比較好的方法是顯示一個對話框,讓用戶進行操作,既然要用對話框,必然離不開 DialogFragment
在 RecordAudioDialogFragment 有一個 newInstance(int maxTime) 的靜態方法供外部調用,如果想設置錄音的最大時長,直接傳參數進去就行了。
好的,敲黑板,重點來了,其實這個對話框的重點部分就是在 onCreateDialog()中,我們先加載了我們自定義的對話框的布局,當點擊錄音的按鈕的時候,先進行相關權限的申請,這里有個巨坑,錄音權限 android.permission.RECORD_AUDIO 在不久前還是普通權限的,不知道什么時候突然變成了危險權限,需要我們進行申請,Google 真是會玩。
public Dialog onCreateDialog(Bundle savedInstanceState) { Dialog dialog = super.onCreateDialog(savedInstanceState); final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_record_audio, null); mFabRecord.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity() , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, 1); }else { onRecord(mStartRecording); mStartRecording = !mStartRecording; } } }); builder.setView(view); return builder.create(); }
三、播放錄音的 PlaybackDialogFragment
其實,如果只是錄音這一塊的話,寫個 MediaPlayer 就可以了,然而還要寫播放的時間進度,以及顯示一個稍微好看點的進度條,我能怎樣,我也很煩啊。
外部調用這個對話框的時候,只需要傳入一個包含錄音文件信息的 RecordingItem,因為包含的信息比較多,所以最好將 RecordingItem 進行序列化。
public static PlaybackDialogFragment newInstance(RecordingItem item) { PlaybackDialogFragment fragment = new PlaybackDialogFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(ARG_ITEM, item); fragment.setArguments(b); return fragment; }
好,重點又來了,來看看 onCreateDialog() 方法,在加載了布局之后,給 mSeekBar 設置監聽,mSeekBar 是一個顯示進度條的控件,當開始播放錄音時候,將錄音文件的時長,設置進 mSeekBar 里面,播放錄音的同時,運行 mSeekBar,通過監聽 mSeekBar 的進度,刷新顯示的播放進度。
public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_media_playback, null); mFileLengthTextView.setText(String.valueOf(mFileLength)); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(mMediaPlayer != null && fromUser) { mMediaPlayer.seekTo(progress); mHandler.removeCallbacks(mRunnable); long minutes = TimeUnit.MILLISECONDS.toMinutes(mMediaPlayer.getCurrentPosition()); long seconds = TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getCurrentPosition()) - TimeUnit.MINUTES.toSeconds(minutes); mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes,seconds)); updateSeekBar(); } else if (mMediaPlayer == null && fromUser) { prepareMediaPlayerFromPoint(progress); updateSeekBar(); } } }); mPlayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onPlay(isPlaying); isPlaying = !isPlaying; } }); mFileLengthTextView.setText(String.format("%02d:%02d", minutes,seconds)); builder.setView(view); return builder.create(); }
當點擊播放錄音的按鈕之后,會調用 onPlay() 方法,然后根據 isPlaying(標識當前是否播放錄音)的值,來調用不同的方法
private void onPlay(boolean isPlaying){ if (!isPlaying) { //currently MediaPlayer is not playing audio if(mMediaPlayer == null) { startPlaying(); //start from beginning } } else { pausePlaying(); } }
我們最關心的,莫過於 startPlaying() 這個方法,這個方法便是來開啟播放錄音的,我們首先將外部傳入的有關的錄音信息,設置給 MediaPlayer,然后開始調用 mMediaPlayer.start() 進行錄音的播放,然后調用 updateSeekbar() 實時更新進度條的內容。當 MediaPlayer 的內容播放完成后,調用 stopPlaying() 方法,關閉 mMediaPlayer
項目地址:
更多文章
相信自己,沒有做不到的,只有想不到的
如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :644196190 微信公眾號:終端研發部