最近有小夥伴經常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
微信公眾號:終端研發部