How to realize the recording function of imitating Wechat by Android
This article mainly introduces Android how to achieve imitation Wechat recording function, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
Implementation method:
1. Add to the xml file
two。 Don't forget to apply for recording permission.
AndPermission.with (MainActivity.this) .permission (Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE) .onGranted (permissions-> {showSelect ();}) .onDenied (permissions-> {Toast.makeText (MainActivity.this, "Please agree to record permission", Toast.LENGTH_SHORT). Show ();}) .start (); private void showSelect () {SoundTextView recordAudio = findViewById (R.id.record_audio) RecordAudio.setOnRecordFinishedListener (new SoundTextView.OnRecordFinishedListener () {@ Override public void newMessage (String path, int duration) {int index = path.lastIndexOf ("/"); String fileName = path.substring (index + 1); Log.e ("recording File", "path=:" + path);}});}
The method of use is very simple as above:
Main classes
Package ant.muxi.com.audiodemo.view; import android.app.Activity;import android.app.Dialog;import android.content.Context;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.widget.AppCompatTextView;import java.io.File;import ant.muxi.com.audiodemo.R;import ant.muxi.com.audiodemo.audio.ProgressTextUtils Import ant.muxi.com.audiodemo.audio.RecordManager;public class SoundTextView extends AppCompatTextView {private Context mContext; private Dialog recordIndicator; private TextView mVoiceTime; private File file; private String type= "1"; / / start recording type=2 by default, and finish recording RecordManager recordManager; File fileto; int level; private long downT; String sountime; public SoundTextView (Context context) {super (context); init ();} public SoundTextView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); this.mContext = context; init () } public SoundTextView (Context context, AttributeSet attrs) {super (context, attrs); this.mContext = context; init ();} private void init () {recordIndicator = new Dialog (getContext (), R.style.jmui_record_voice_dialog); recordIndicator.setContentView (R.layout.jmui_dialog_record_voice); mVoiceTime = (TextView) recordIndicator.findViewById (R.id.voice_time); file = new File (Environment.getExternalStorageDirectory () + "/ recoder.amr") Fileto = new File (Environment.getExternalStorageDirectory () + "/ recoder.mp3"); recordManager = new RecordManager ((Activity) mContext, String.valueOf (file), String.valueOf (fileto)); recordManager.setOnAudioStatusUpdateListener (new RecordManager.OnAudioStatusUpdateListener () {@ Override public void onUpdate (double db) {/ / get decibel if (null! = recordIndicator) {level = (int) db; handler.sendEmptyMessage (0x111);}) } Handler handler = new Handler () {@ Override public void handleMessage (Message msg) {super.handleMessage (msg); switch (msg.what) {case 0x111: sountime = ProgressTextUtils.getSecsProgress (System.currentTimeMillis ()-downT); long time = System.currentTimeMillis ()-downT; mVoiceTime.setText (ProgressTextUtils.getProgressText (time)); / / judgment time judetime (Integer.parseInt (sountime)); break;} Public void judetime (int time) {if (time > 14) {/ / end recording Toast.makeText (mContext, "recording cannot exceed 15 seconds", Toast.LENGTH_SHORT). Show (); recordManager.stop_mp3 (); new Thread () {@ Override public void run () {super.run (); recordManager.saveData (); finishRecord (fileto.getPath (), sountime);}. Start (); recordIndicator.dismiss (); type = "2" } @ Override public boolean onTouchEvent (MotionEvent event) {int action = event.getAction (); switch (action) {case MotionEvent.ACTION_DOWN: if (type.equals ("1")) {/ / start sending time downT = System.currentTimeMillis (); recordManager.start_mp3 (); recordIndicator.show ();} else {Log.e ("- log-", "you have finished recording:");} return true Case MotionEvent.ACTION_UP: if (type.equals ("1")) {try {if (Integer.parseInt (sountime) > 2) {recordManager.stop_mp3 (); new Thread () {@ Override public void run () {super.run (); recordManager.saveData (); finishRecord (fileto.getPath (), sountime);}. Start (); if (recordIndicator.isShowing ()) {recordIndicator.dismiss () } type = "2";} else {recordManager.stop_mp3 (); if (recordIndicator.isShowing ()) {recordIndicator.dismiss ();} sountime = null; Toast.makeText (mContext, "recording time is less than 3 seconds, please re-record", Toast.LENGTH_SHORT). Show ();} catch (Exception e) {recordManager.stop_mp3 () If (recordIndicator.isShowing ()) {recordIndicator.dismiss ();} sountime = null; Toast.makeText (mContext, "recording time is less than 3 seconds, please re-record", Toast.LENGTH_SHORT). Show ();}} break; case MotionEvent.ACTION_CANCEL: if (recordIndicator.isShowing ()) {recordIndicator.dismiss ();} break;} return super.onTouchEvent (event) } / / after recording, load ListView item private void finishRecord (String path, String time) {if (onRecordFinishedListener! = null) {onRecordFinishedListener.newMessage (path, Integer.parseInt (time)); type = "1";} / / send voice / / Toasts.toast (getContext (), "you have finished recording a voice" + myRecAudioFile);} private OnRecordFinishedListener onRecordFinishedListener; public void setOnRecordFinishedListener (OnRecordFinishedListener onRecordFinishedListener) {this.onRecordFinishedListener = onRecordFinishedListener;} public interface OnRecordFinishedListener {void newMessage (String path, int duration);}}
Major recording management classes
Public class RecordManager {/ / recorded into MP3 format. / * * Activity required during construction, mainly used to obtain the path of the folder * / private Activity activity; / * * file code * / public static final int RAW = 0X00000001; public static final int MP3 = 0X00000002; / * * file path * / private String rawPath = null; private String mp3Path = null; / * * sampling frequency * / private static final int SAMPLE_RATE = 11025; / * * some variables required for recording * / private short [] mBuffer; private AudioRecord mRecorder / * * recording status * / private boolean isRecording = false; / * * whether to convert ok*/ private boolean convertOk = false; public RecordManager (Activity activity, String rawPath, String mp3Path) {this.activity = activity; this.rawPath = rawPath; this.mp3Path = mp3Path;} / * * start recording * / public boolean start_mp3 () {/ / if recording is in progress, return if (isRecording) {return isRecording;} / / initialize if (mRecorder = null) {initRecorder () } getFilePath (); mRecorder.startRecording (); startBufferedWrite (new File (rawPath)); isRecording = true; return isRecording;} / * * stop recording and convert files, which is probably a time-consuming operation. It is recommended to do * / public boolean stop_mp3 () {if (! isRecording) {return isRecording;} / / stop mRecorder.stop () in the background; isRecording = false / / TODO / / start conversion (only these two sentences in the conversion code) / / FLameUtils lameUtils = new FLameUtils (1, SAMPLE_RATE, 96); / / convertOk= lameUtils.raw2mp3 (rawPath, mp3Path); / / return isRecording ^ convertOk;// convertOk==true,return true return isRecording;} public void saveData () {FLameUtils lameUtils = new FLameUtils (1, SAMPLE_RATE, 96); convertOk= lameUtils.raw2mp3 (rawPath, mp3Path) } / * * get the path to the file * / public String getFilePath (int fileAlias) {if (fileAlias = = RAW) {return rawPath;} else if (fileAlias = = MP3) {return mp3Path;} else return null;} / * * Clean the file * / public void cleanFile (int cleanFlag) {File f = null; try {switch (cleanFlag) {case MP3: F = new File (mp3Path); if (f.exists ()) f.delete (); break Case RAW: F = new File (rawPath); if (f.exists ()) f.delete (); break; case RAW | MP3: f = new File (rawPath); if (f.exists ()) f.delete (); f = new File (mp3Path); if (f.exists ()) f.delete (); break;} f = null;} catch (Exception e) {e.printStackTrace () }} / * * close, you can first call cleanFile to clean up the file * / public void close () {if (mRecorder! = null) mRecorder.release (); activity = null;} / * * initialize * / private void initRecorder () {int bufferSize = AudioRecord.getMinBufferSize (SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); mBuffer = new short [bufferSize] MRecorder = new AudioRecord (MediaRecorder.AudioSource.MIC, SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);} / * * set the path, the first is the raw file, the second is the mp3 file * / private void getFilePath () {try {String folder = "audio_recorder_2_mp3"; String fileName = String.valueOf (System.currentTimeMillis ()) If (rawPath = = null) {File raw = new File (activity.getDir (folder, activity.MODE_PRIVATE), fileName + ".raw"); raw.createNewFile (); rawPath = raw.getAbsolutePath (); raw = null;} if (mp3Path = = null) {File mp3 = new File (activity.getDir (folder, activity.MODE_PRIVATE), fileName + ".mp3"); mp3.createNewFile (); mp3Path = mp3.getAbsolutePath (); mp3 = null } Log.d ("rawPath", rawPath); Log.d ("mp3Path", mp3Path);} catch (Exception e) {e.printStackTrace ();}} / * * execute the cmd command and wait for the result * / private boolean runCommand (String command) {boolean ret = false; Process process = null; try {process = Runtime.getRuntime (). Exec (command); process.waitFor (); ret = true;} catch (Exception e) {e.printStackTrace () } finally {try {process.destroy ();} catch (Exception e) {e.printStackTrace ();}} return ret;} / * * write to raw file * / private void startBufferedWrite (final File file) {Object mLock = new Object (); new Thread (new Runnable () {@ Override public void run () {DataOutputStream output = null; try {output = new DataOutputStream (new BufferedOutputStream (new FileOutputStream (file) While (isRecording) {/ / start recording int readSize = mRecorder.read (mBuffer, 0, mBuffer.length); / / is the actual read data length for (int I = 0; I < readSize; ibuffer +) {output.writeShort (mBuffer [I]);} long v = 0; / / take out the buffer content and perform square sum operation for (int I = 0; I < mBuffer.length) ) {v + = mBuffer [I] * mBuffer [I];} / / the sum of squares divided by the total length of the data to get the volume. Double mean = v / (double) readSize; double volume = 10 * Math.log10 (mean); synchronized (mLock) {try {if (null! = audioStatusUpdateListener) {audioStatusUpdateListener.onUpdate (volume);} mLock.wait (100);} catch (InterruptedException e) {e.printStackTrace ();}} catch (IOException e) {e.printStackTrace () } finally {if (output! = null) {try {output.flush ();} catch (IOException e) {e.printStackTrace ();} finally {try {output.close ();} catch (IOException e) {e.printStackTrace ();}}) .start ();} public RecordManager.OnAudioStatusUpdateListener audioStatusUpdateListener; public void setOnAudioStatusUpdateListener (RecordManager.OnAudioStatusUpdateListener audioStatusUpdateListener) {this.audioStatusUpdateListener = audioStatusUpdateListener } public interface OnAudioStatusUpdateListener {public void onUpdate (double db);}} Thank you for reading this article carefully. I hope the article "how to achieve the recording function of imitating Wechat" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support and pay attention to the industry information channel. More related knowledge is waiting for you to learn!