Android recording function directly take to use

Foreword

Recent projects need to use the recording features, borrowed a buddy of foreign project https://github.com/dkim0419/SoundRecorder , get after demand, spent some time recording packaged into a tool bag, for everyone to share, click here need the source code

First renderings posted for everyone to see it and see the function of this recording package

First, realize recording of Service

This class can be said that the core of this package, and if you understand this Service, recording this one basically no problem.

Recording mainly using MediaRecoder this class, recorded sound, and then we take a look at the specific implementation.

public class RecordingService extends Service {
 
    private String mFileName;
    private String mFilePath;
 
    private MediaRecorder mRecorder;
 
    private long mStartingTimeMillis;
    private long mElapsedMillis;
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startRecording();
        return START_STICKY;
    }
 
    @Override
    public void onDestroy() {
        if (mRecorder != null) {
            stopRecording();
        }
        super.onDestroy();
    }
 
    // 开始录音
    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;
    }
 
}

You can see there is a startRecording () method onStartCommand () inside, start the RecordingService of time outside, we will call this startRecording () method to start recording.

In startRecording () method first calls setFileNameAndPath method, initialize the name of the audio file and save path, in order to allow each audio file has a unique name, I call System.currentMillis () spliced ​​to record the name of the file inside.

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());
   }

After setting the name and path of the file saved on mRecorder a series of parameter settings, this is an instance mRecorder MediaRecorder, specializing in storage for recording.

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");
       }

After setting up the parameters, start mRecorder start recording, you can see after the start mRecorder start recording, I will also be assigned to the current time mStartingTimeMills, here primarily to record the length of the recording, wait until the end of the recording to obtain a current time, and then specifically the two subtraction time, recording can get long.

Wait until the end of the recording, stop the service, it will callback RecordingService of onDestroy () method, which is invoked when stopRecording () method, close mRecorder, and save the file with the information recording SharedPreferences, finally mRecorder blank, prevent memory leaks

 public void stopRecording() {
        mRecorder.stop();
        mElapsedMillis = (System.currentTimeMillis() - mStartingTimeMillis);
        mRecorder.release();
 
        getSharedPreferences("sp_name_audio", MODE_PRIVATE)
                .edit()
                .putString("audio_name", mFileName)
                .putString("audio_path", mFilePath)
                .putLong("elpased", mElapsedMillis)
                .apply();
        if (mIncrementTimerTask != null) {
            mIncrementTimerTask.cancel();
            mIncrementTimerTask = null;
        }
 
        mRecorder = null;
    }

Second, the display RecordAudioDialogFragment recording interface

When the user, can not let the App jump to another interface it, so the user experience is not very good, a better approach is to display a dialog box that allows the user to operate, since the use dialog boxes, can not be separated 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);
        }
    }
}

Can be seen in RecordAudioDialogFragment a newInstance (int maxTime) static method for external calls, if you want to set the maximum recording length, pass parameters directly into the line.

Well, knock on the blackboard, the focus here, in fact, the focus of this section of the dialog is in onCreateDialog (), we have to load our custom layout dialog box, click on the record button when the first related rights application, there is a giant pit, recording rights android.permission.RECORD_AUDIO until recently the general authority, do not know when suddenly became a dangerous permission, we need to apply, Google will 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 a good application permissions will call onRecord () This method, then invert boolean mStartRecording, so do not write ugly if else, and directly change the value of mStartRecording is then processed in onRecord () inside

What followed did look onRecord

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, in fact, I have not done a big deal, just create a folder where to save the recording, then start RecordingService on and off depending on the value mStartRecording Bale. When it is invoked by the way it started mChronometer timing show that this is a timed control displays a native Android.

Third, play a recording of PlaybackDialogFragment

In fact, if only recording this one, then write a MediaPlayer on it, but he wrote the play schedule, and show a little good-looking point of the progress bar, how can I, I also annoying ah.

External call this dialog box, you can just pass a file that contains audio RecordingItem information, the information because there's more, so it is best to RecordingItem be serialized.

 public static PlaybackDialogFragment newInstance(RecordingItem item) {
        PlaybackDialogFragment fragment = new PlaybackDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable(ARG_ITEM, item);
        fragment.setArguments(b);
        return fragment;
    }

Well, the focus again, take a look at onCreateDialog () method after loading the layout, set the monitor to mSeekBar, mSeekBar control is a progress bar shows when recording starts playing when the long recording file, set into mSeekBar inside, while playing the recording, run mSeekBar, by listening mSeekBar of progress, refresh the display of 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();
    }

When you click the button to play the recording, calls onPlay () method, and then depending on the value isPlaying (identifies the currently playing recording), and to call different methods

 private void onPlay(boolean isPlaying){
        if (!isPlaying) {
            if(mMediaPlayer == null) {
                startPlaying(); //start from beginning
            } 
        } else {
            pausePlaying();
        }
    }

We are most concerned about, than startPlaying () This method, which is open to play the recording, we first external incoming recorded messages relating to setting MediaPlayer, and then start calling mMediaPlayer.start () to record on play, then call updateSeekbar () real-time updates of the progress bar. When MediaPlayer content has finished playing, call stopPlaying () method to close the 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 entire contents of this article, can look like

IV. Written in the last

Many people new to this industry in the face of time or bottleneck, there will always encounter some problems, such as learning a period of time feel no sense of direction, I do not know from where to start to learn, and I am finishing up some of the information needed can be free for everyone to share
if you like my articles, willing to walk with a group of senior developers exchange of learning, then get more manufacturers interview advice and guidance, welcome to my Android development cooperation group exchanges: 1018342383
or click on the link to join a group chat [Android] development and exchange: https://jq.qq.com/?_wv=1027&k=5WjVzJT**

Reproduced in: https: //www.jianshu.com/p/f6bb18bf105d

Guess you like

Origin blog.csdn.net/weixin_33709590/article/details/91251676