.putString("audio_name", mFileName) .putString("audio_path", mFilePath) .putLong("elpased", mElapsedMillis) .apply(); if (mIncrementTimerTask != null) { mIncrementTimerTask.cancel(); mIncrementTimerTask = null; } mRecorder = null; }
```
###2, Displays the RecordAudioDialogFragment of the recording interface
When users are, they can't let the App jump to another interface. In this way, the user experience is not very good. A better way is to display a dialog box for users to operate. Since the dialog box is used, it must be inseparable from DialogFragment.
public class RecordAudioDialogFragment extends DialogFragment { private boolean mStartRecording = true; long timeWhenPaused = 0; private FloatingActionButton mFabRecord; private Chronometer mChronometerTime; public static RecordAudioDialogFragment newInstance(int maxTime) { RecordAudioDialogFragment dialogFragment = new RecordAudioDialogFragment(); Bundle bundle = new Bundle(); bundle.putInt("maxTime", maxTime); dialogFragment.setArguments(bundle); return dialogFragment; } @NonNull @Override 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(); } private void onRecord(boolean start) { Intent intent = new Intent(getActivity(), RecordingService.class); if (start) { File folder = new File(Environment.getExternalStorageDirectory() + "/SoundRecorder"); if (!folder.exists()) { folder.mkdir(); } mChronometerTime.setBase(SystemClock.elapsedRealtime()); mChronometerTime.start(); getActivity().startService(intent); } else { mChronometerTime.stop(); timeWhenPaused = 0; getActivity().stopService(intent); } } }
You can see that there is a static method of newInstance(int maxTime) in RecordAudioDialogFragment for external calls. If you want to set the maximum duration of recording, just pass the parameter directly.
OK, knock on the blackboard. Here's the key point. In fact, the key part of this dialog box is that in onCreateDialog(), we first load the layout of our customized dialog box. When clicking the recording button, we first apply for relevant permissions. Here is a huge pit, recording permission Android permission. RECORD_ Audio was an ordinary authority not long ago. I don't know when it suddenly became a dangerous authority. We need to apply. Google can really play.
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(); } ``` After applying for permission, it will be called onRecord() This method, and then boolean mStartRecording Reverse so you don't have to write ugly if else Yes, change directly mStartRecording And then onRecord() Handle it inside Next look onRecord What did you do
private void onRecord(boolean start) {
Intent intent = new Intent(getActivity(), RecordingService.class);
if (mStartRecording) {
File folder = new File(Environment.getExternalStorageDirectory() + "/SoundRecorder");
if (!folder.exists()) {
folder.mkdir();
}
mChronometerTime.setBase(SystemClock.elapsedRealtime()); mChronometerTime.start(); getActivity().startService(intent); } else { mChronometerTime.stop(); timeWhenPaused = 0; getActivity().stopService(intent); } }
Well, actually, I didn't do anything big. I just created a folder to save the recording files, and then according to mStartRecording The value of RecordingService Just start and shut down. It also started at the start-up mChronometer The timing shows that this is a Android A native control that displays timing. ###3, PlaybackDialogFragment for playing the recording In fact, if it's just recording, write one MediaPlayer It's OK. However, I have to write the playback time progress and display a slightly better progress bar. What can I do? I'm also very annoyed. When calling this dialog box externally, you only need to pass in a message containing the information of the recording file RecordingItem,Because it contains a lot of information, it is best to RecordingItem Serialize.
public static PlaybackDialogFragment newInstance(RecordingItem item) {
PlaybackDialogFragment fragment = new PlaybackDialogFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(ARG_ITEM, item);
fragment.setArguments(b);
return fragment;
}
OK, here's the point again. Let's have a look onCreateDialog() Method, after loading the layout, give mSeekBar Set listening, mSeekBar It is a control to display the progress bar. When playing the recording, set the duration of the recording file into mSeekBar Inside, while playing the recording, run mSeekBar,By listening mSeekBar Refresh the displayed playback progress.
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_media_playback, null); mTvFileLength.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; } }); mTvFileLength.setText(String.format("%02d:%02d", minutes,seconds)); builder.setView(view); return builder.create(); }
After clicking the play recording button, it will call onPlay() Method, and then according to isPlaying(A value that identifies whether the recording is currently playing or not to call different methods
private void onPlay(boolean isPlaying){
if (!isPlaying) {
if(mMediaPlayer == null) {
startPlaying(); //start from beginning
}
} else {
pausePlaying();
}
}
What we care about most is startPlaying() This method is used to start playing recording. First, we set the relevant recording information imported from the outside to MediaPlayer,Then start calling mMediaPlayer.start() Play the tape and then call it. updateSeekbar() Update the contents of the progress bar in real time. When MediaPlayer After the content is played, it is called. stopPlaying() Method, close mMediaPlayer.
private void startPlaying() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(item.getFilePath());
mMediaPlayer.prepare();
mSeekBar.setMax(mMediaPlayer.getDuration());
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mMediaPlayer.start(); } }); mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { stopPlaying(); } }); updateSeekBar(); }
```
The above is the whole content of this article. Those who like it can pay attention to it
###IV Write at the end
Many people will always encounter some problems when they first come into contact with this industry or when they encounter a bottleneck period. For example, after learning for a period of time, they don't feel a sense of direction and don't know where to start to learn. I have sorted out some materials and can share them for free
CodeChina open source project: Android learning notes summary + mobile architecture Video + big factory interview real questions + project actual combat source code
I started to study there. I sorted out some materials for this. What I need can be shared with you free of charge**
[external chain picture transferring... (img-5BDcMQx5-1630903838623)]
[external chain picture transferring... (IMG agepkk4s-1630903838625)]