Android development-imitation WeChat voice intercom recording

Source: Internet
Author: User
Tags gety

Android development-audio-like intercom recording

Since its appearance, it has achieved good results, making it easier for people to communicate with each other. The audio recording Implementation of The Voice intercom is also easy to implement today. Here, I encapsulate the button as a control and implement the decoupling between the recording and the interface in the Policy mode, in order to facilitate our different requirements on the recording method in actual situations (for example, we can no longer use MediaRecorder to implement the wav format encoding, but can only use AudioRecord for processing ).


1. we can see that the voice intercom is implemented by clicking the Button, so here I choose to re-control it to inherit from the Button and override the onTouchEvent method, to determine the recording.
2. In the onTouchEvent method,
When we press the button, we first display the dialog box for recording, then call the recording preparation method and start recording, and then enable a timer thread to obtain the recording volume every 0.1 seconds, the Handler is used to update the display image in the Dialog according to the volume;
When we move the finger, if the distance between the finger and the top is greater than 50, the prompt for unrecording the finger is displayed in the Dialog and the isCanceled variable is used to indicate whether the recording is canceled) set this parameter to true. When the distance between the preceding operations is less than 20, we can restore the Dialog image and set isCanceled to false;
When we raise our finger, we first close the recording dialog box, then call the recording stop method and close the timer thread, and then determine whether to cancel the recording. If so, we will delete the recording file, otherwise, check whether the timing time is too short and call the recordEnd method in the callback interface.
3. In order to adapt to different recording requirements, I use a policy mode to process each recording method. Each method is considered as a different strategy and can be rewritten as needed.


1. In the onTouchEvent return value, the system should return true to block other subsequent touch events. Otherwise, when the finger slides away from the Button, it will not be able to respond to our touch method.
2. Do not forget to add permissions to your App:

Code reference

RecordButton class, our custom control, re-wrote the onTouchEvent Method

Package com. example. recordtest; import android. annotation. suppressLint; import android. app. dialog; import android. content. context; import android. OS. handler; import android. OS. message; import android. util. attributeSet; import android. view. gravity; import android. view. layoutInflater; import android. view. motionEvent; import android. view. view; import android. widget. button; import android. widget. imageView; import Ndroid. widget. textView; import android. widget. toast; public class RecordButton extends Button {private static final int MIN_RECORD_TIME = 1; // minimum recording time, in seconds private static final int RECORD_OFF = 0; // not recording private static final int RECORD_ON = 1; // recording private Dialog mRecordDialog; private RecordStrategy mAudioRecorder; private Thread mRecordThread; private RecordListener listener; private int recor DState = 0; // recording status private float recodeTime = 0.0f; // recording duration. If the recording time is too short, the recording fails. private double voiceValue = 0.0; // The recording volume value private boolean isCanceled = false; // whether to cancel the recording private float downY; private TextView dialogTextView; private ImageView dialogImg; private Context mContext; public RecordButton (Context context) {super (context); // TODO Auto-generated constructor stub init (context);} public RecordBu Tton (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); // TODO Auto-generated constructor stub init (context );} public RecordButton (Context context, AttributeSet attrs) {super (context, attrs); // TODO Auto-generated constructor stub init (context);} private void init (Context context) {mContext = context; this. setText (Press and hold);} public void setAudioRecord (Record Strategy record) {this. mAudioRecorder = record;} public void setRecordListener (RecordListener listener) {this. listener = listener;} // display Dialog private void showVoiceDialog (int flag) {if (mRecordDialog = null) {mRecordDialog = new diener (mContext, R. style. dialogstyle); mRecordDialog. setContentView (R. layout. dialog_record); dialogImg = (ImageView) mRecordDialog. findViewById (R. id. record_di Alog_img); dialogTextView = (TextView) mRecordDialog. findViewById (R. id. record_dialog_txt);} switch (flag) {case 1: dialogImg. setImageResource (R. drawable. record_cancel); dialogTextView. setText (with your finger removed, you can cancel the recording); this. setText (loosen your finger to cancel the recording); break; default: dialogImg. setImageResource (R. drawable. record_animate_01); dialogTextView. setText (sliding up to cancel recording); this. setText (loosen your finger to complete the recording); break;} dialogTextView. setTextSiz E (14); mRecordDialog. show () ;}// the recording time is too short. Toast displays private void showWarnToast (String toastText) {Toast toast = new Toast (mContext); View warnView = LayoutInflater. from (mContext ). inflate (R. layout. toast_warn, null); toast. setView (warnView); toast. setGravity (Gravity. CENTER, 0, 0); // The starting point is the middle toast. show () ;}// enable recording timer Thread private void callRecordTimeThread () {mRecordThread = new Thread (recordThread); mRe CordThread. start () ;}// change the private void setDialogImage () {if (voiceValue <600.0) {dialogImg with the recording volume. setImageResource (R. drawable. record_animate_01);} else if (voiceValue> 600.0 & voiceValue <1000.0) {dialogImg. setImageResource (R. drawable. record_animate_02);} else if (voiceValue> 1000.0 & voiceValue <1200.0) {dialogImg. setImageResource (R. drawable. record_animate_03);} else if (VoiceValue> 1200.0 & voiceValue <1400.0) {dialogImg. setImageResource (R. drawable. record_animate_04);} else if (voiceValue> 1400.0 & voiceValue <1600.0) {dialogImg. setImageResource (R. drawable. record_animate_05);} else if (voiceValue> 1600.0 & voiceValue <1800.0) {dialogImg. setImageResource (R. drawable. record_animate_06);} else if (voiceValue> 1800.0 & voiceValue <2000.0) {dialogIm G. setImageResource (R. drawable. record_animate_07);} else if (voiceValue> 2000.0 & voiceValue <3000.0) {dialogImg. setImageResource (R. drawable. record_animate_08);} else if (voiceValue> 3000.0 & voiceValue <4000.0) {dialogImg. setImageResource (R. drawable. record_animate_09);} else if (voiceValue> 4000.0 & voiceValue <6000.0) {dialogImg. setImageResource (R. drawable. record_animate_10);} els E if (voiceValue> 6000.0 & voiceValue <8000.0) {dialogImg. setImageResource (R. drawable. record_animate_11);} else if (voiceValue> 8000.0 & voiceValue <10000.0) {dialogImg. setImageResource (R. drawable. record_animate_12);} else if (voiceValue> 10000.0 & voiceValue <12000.0) {dialogImg. setImageResource (R. drawable. record_animate_13);} else if (voiceValue> 12000.0) {dialogImg. setImageReso Urce (R. drawable. record_animate_14); }}// recording thread private Runnable recordThread = new Runnable () {@ Override public void run () {recodeTime = 0.0f; while (recordState = RECORD_ON) {try {Thread. sleep (100); recodeTime + = 0.1; // gets the volume and updates the dialog if (! IsCanceled) {voiceValue = mAudioRecorder. getampller (); recordHandler. sendEmptyMessage (1) ;}} catch (InterruptedException e) {e. printStackTrace () ;}}}}; @ SuppressLint (HandlerLeak) private Handler recordHandler = new Handler () {@ Override public void handleMessage (Message msg) {setDialogImage () ;}}; @ Override public boolean onTouchEvent (MotionEvent event) {// TODO Auto-generated method s Tub switch (event. getAction () {case MotionEvent. ACTION_DOWN: // press the button if (recordState! = RECORD_ON) {showVoiceDialog (0); downY = event. getY (); if (mAudioRecorder! = Null) {mAudioRecorder. ready (); recordState = RECORD_ON; mAudioRecorder. start (); callRecordTimeThread () ;}} break; case MotionEvent. ACTION_MOVE: // float moveY = event. getY (); if (downY-moveY> 50) {isCanceled = true; showVoiceDialog (1) ;}if (downY-moveY <20) {isCanceled = false; showVoiceDialog (0);} break; case MotionEvent. ACTION_UP: // release the finger if (recordState = RECORD_ON) {recordS Tate = RECORD_OFF; if (mRecordDialog. isShowing () {mRecordDialog. dismiss ();} mAudioRecorder. stop (); mRecordThread. interrupt (); voiceValue = 0.0; if (isCanceled) {mAudioRecorder. deleteOldFile ();} else {if (recodeTime <MIN_RECORD_TIME) {showWarnToast (recording failed due to too short time); mAudioRecorder. deleteOldFile ();} else {if (listener! = Null) {listener. recordEnd (mAudioRecorder. getFilePath () ;}} isCanceled = false; this. setText (Press and hold the speaker);} break;} return true;} public interface RecordListener {public void recordEnd (String filePath );}}

Dialog layout:


Toast layout with a short recording time:


Custom Dialogstyle, dialog box style

RecordStrategy recording policy interface

Package com. example. recordtest;/*** RecordStrategy recording policy interface * @ author acer */public interface RecordStrategy {/*** prepare the recording here, reset the recording file name */public void ready ();/*** start recording */public void start ();/*** End recording */public void stop (); /*** Delete the original file when the recording fails */public void deleteOldFile ();/*** obtain the volume of the recording * @ return */public double getampl (); /*** return the complete recording file path * @ return */public String getFilePath ();}

An individual recording Practice strategy

Package com. example. recordtest; import java. io. file; import java. io. IOException; import java. text. simpleDateFormat; import java. util. date; import android. media. mediaRecorder; import android. OS. environment; public class AudioRecorder implements RecordStrategy {private MediaRecorder recorder; private String fileName; private String fileFolder = Environment. getExternalStorageDirectory (). getPath () +/TestRe Cord; private boolean isRecording = false; @ Override public void ready () {// TODO Auto-generated method stub File file = new File (fileFolder); if (! File. exists () {file. mkdir ();} fileName = getCurrentDate (); recorder = new MediaRecorder (); recorder. setOutputFile (fileFolder +/+ fileName +. amr); recorder. setAudioSource (MediaRecorder. audioSource. MIC); // set the audio source of the MediaRecorder to the microphone recorder. setOutputFormat (MediaRecorder. outputFormat. RAW_AMR); // set the audio format recorder recorded by MediaRecorder. setAudioEncoder (MediaRecorder. audioEncoder. AMR_NB); // sets MediaRecorder recording Audio is encoded as amr} // use the current time as the file name private String getCurrentDate () {SimpleDateFormat formatter = new SimpleDateFormat (yyyy_MM_dd_HHmmss); Date curDate = new Date (System. currentTimeMillis (); // obtain the current time String str = formatter. format (curDate); return str ;}@ Override public void start () {// TODO Auto-generated method stub if (! IsRecording) {try {recorder. prepare (); recorder. start ();} catch (IllegalStateException e) {// TODO Auto-generated catch block e. printStackTrace ();} catch (IOException e) {// TODO Auto-generated catch block e. printStackTrace () ;}isrecording = true ;}@ Override public void stop () {// TODO Auto-generated method stub if (isRecording) {recorder. stop (); recorder. release (); isRecording = false; }}@ Override public void deleteOldFile () {// TODO Auto-generated method stub File file = new File (fileFolder ++ fileName +. amr); file. deleteOnExit () ;}@ Override public double getAmplitude () {// TODO Auto-generated method stub if (! IsRecording) {return 0;} return recorder. getmaxamplpath () ;}@ Override public String getFilePath () {// TODO Auto-generated method stub return fileFolder ++ fileName +. amr ;}}


package com.example.recordtest;import android.os.Bundle;import;import android.view.Menu;public class MainActivity extends Activity {    RecordButton button;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = (RecordButton) findViewById(;        button.setAudioRecord(new AudioRecorder());    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(, menu);        return true;    }}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.