Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the recording function of imitating Wechat by Android

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail how Android realizes the function of imitating Wechat recording. The editor thinks it is very practical, so I share it for you as a reference. I hope you can get something after reading this article.

Abstract: the demand is to develop a function similar to Wechat voice, no voice to text. I read some code on the Internet, but I can't use it directly. There is something wrong with the logic of some code, so I want to post my code for reference only.

Features:

A. Set the maximum recording duration and recording countdown (to facilitate testing, the maximum recording length is set to 15 seconds, and the start countdown is set to 7 seconds)

B. Check recording and storage permissions before recording

Source code:

1. Recording dialog management class DialogManager:

/ * function: recording dialog management class * / public class DialogManager {private AlertDialog.Builder builder; private AlertDialog dialog; private ImageView mIcon; private ImageView mVoice; private TextView mLabel; private Context context; / * constructor * * @ Context * / public DialogManager (Context context) at param context Activity level {this.context = context } / * dialog box showing recording * / public void showRecordingDialog () {builder = new AlertDialog.Builder (context, R.style.AudioRecorderDialogStyle); LayoutInflater inflater = LayoutInflater.from (context); View view = inflater.inflate (R.layout.audio_recorder_dialog, null); mIcon = view.findViewById (R.id.iv_dialog_icon); mVoice = view.findViewById (R.id.iv_dialog_voice); mLabel = view.findViewById (R.id.tv_dialog_label); builder.setView (view) Dialog = builder.create (); dialog.show (); dialog.setCanceledOnTouchOutside (false);} / * status while playing * / public void recording () {if (dialog! = null & & dialog.isShowing ()) {/ / display status mIcon.setVisibility (View.VISIBLE); mVoice.setVisibility (View.VISIBLE); mLabel.setVisibility (View.VISIBLE); mIcon.setImageResource (R.drawable.ic_audio_recorder); mVoice.setImageResource (R.drawable.ic_audio_v1) MLabel.setText (R.string.audio_record_dialog_up_to_cancel);}} / * displays the dialog box you want to cancel * / public void wantToCancel () {if (dialog! = null & & dialog.isShowing ()) {/ / display status mIcon.setVisibility (View.VISIBLE); mVoice.setVisibility (View.GONE); mLabel.setVisibility (View.VISIBLE); mIcon.setImageResource (R.drawable.ic_audio_cancel) MLabel.setText (R.string.audio_record_dialog_release_to_cancel);}} / * dialog box with too short display time * / public void tooShort () {if (dialog! = null & & dialog.isShowing ()) {/ / display status mIcon.setVisibility (View.VISIBLE); mVoice.setVisibility (View.GONE); mLabel.setVisibility (View.VISIBLE); mLabel.setText (R.string.audio_record_dialog_too_short) }} / / display canceled dialog public void dismissDialog () {if (dialog! = null & & dialog.isShowing ()) {/ / display status dialog.dismiss (); dialog = null }} / * dialog box showing update volume level * * @ param level 1-7 * / public void updateVoiceLevel (int level) {if (dialog! = null & & dialog.isShowing ()) {/ / display status mIcon.setVisibility (View.VISIBLE); mVoice.setVisibility (View.VISIBLE); mLabel.setVisibility (View.VISIBLE); int resId = context.getResources (). GetIdentifier ("ic_audio_v" + level, "drawable", context.getPackageName ()) MVoice.setImageResource (resId);}} public void updateTime (int time) {if (dialog! = null & & dialog.isShowing ()) {/ / display status mIcon.setVisibility (View.VISIBLE); mVoice.setVisibility (View.VISIBLE); mLabel.setVisibility (View.VISIBLE); mLabel.setText (time + "s");}

2. Recording management AudioManager

/ * function: recording management class * / public class AudioManager {private MediaRecorder mMediaRecorder; private String mDir; private String mCurrentFilePath; private static AudioManager mInstance; private boolean isPrepared; private AudioManager (String dir) {this.mDir = dir;} / / Singleton mode: instantiate AudioManager here and pass in the recording file address public static AudioManager getInstance (String dir) {if (mInstance = = null) {synchronized (AudioManager.class) {if (mInstance = = null) {mInstance = new AudioManager (dir) } return mInstance;} / * callback ready * / public interface AudioStateListener {void wellPrepared ();} public AudioStateListener mListener; / * callback method * / public void setOnAudioStateListener (AudioStateListener listener) {mListener = listener;} / * prepare * / public void prepareAudio () {try {isPrepared = false; File dir = FileUtils.createNewFile (mDir); String fileName = generateFileName (); File file = new File (dir, fileName); mCurrentFilePath = file.getAbsolutePath () Logger.t ("AudioManager"). I ("audio file name:" + mCurrentFilePath); mMediaRecorder = new MediaRecorder (); / / set the output file mMediaRecorder.setOutputFile (mCurrentFilePath); / / set the audio source of MediaRecorder to microphone mMediaRecorder.setAudioSource (MediaRecorder.AudioSource.MIC); / / set the audio format mMediaRecorder.setOutputFormat (MediaRecorder.OutputFormat.MPEG_4); / / set the audio format to AAC mMediaRecorder.setAudioEncoder (MediaRecorder.AudioEncoder.AAC); / / prepare for recording mMediaRecorder.prepare () / / start mMediaRecorder.start (); / / prepare to end isPrepared = true; if (mListener! = null) {mListener.wellPrepared ();}} catch (Exception e) {e.printStackTrace ();} / * randomly generated file name * / private String generateFileName () {return UUID.randomUUID (). ToString () + ".m4a" } public int getVoiceLevel (int maxLevel) {if (isPrepared) {try {/ / get the maximum amplitude getMaxAmplitude () 1-32767 return maxLevel * mMediaRecorder.getMaxAmplitude () / 32768 + 1;} catch (Exception e) {}} return 1;} / * * release resources * / public void release () {if (mMediaRecorder! = null) {mMediaRecorder.stop (); mMediaRecorder.release (); mMediaRecorder = null;}} public void cancel () {release () If (mCurrentFilePath! = null) {File file = new File (mCurrentFilePath); FileUtils.deleteFile (file); mCurrentFilePath = null;}} public String getCurrentFilePath () {return mCurrentFilePath;}}

3. Customize the recording button AudioRecorderButton

/ * function: recording button * / public class AudioRecorderButton extends AppCompatButton {private Context mContext; / / cancel recording Y-axis displacement private static final int DISTANCE_Y_CANCEL = 80; / / maximum recording time limit private static final int AUDIO_RECORDER_MAX_TIME = 15; / / recording countdown time private static final int AUDIO_RECORDER_COUNT_DOWN = 7; / / status private static final int STATE_NORMAL = 1ramp / default state private static final int STATE_RECORDING = 2 / / recording private static final int STATE_WANT_TO_CANCEL = 3ramp / wish to cancel / / current status private int mCurrentState = STATE_NORMAL; / / has started recording private boolean isRecording = false; / / whether to trigger onLongClick private boolean mReady; private DialogManager mDialogManager; private AudioManager mAudioManager; private android.media.AudioManager audioManager; public AudioRecorderButton (Context context) {this (context, null);} public AudioRecorderButton (Context context, AttributeSet attrs) {super (context, attrs); this.mContext = context MDialogManager = new DialogManager (context); audioManager = (android.media.AudioManager) context.getSystemService (Context.AUDIO_SERVICE); String dir = SdUtils.getCustomFolder ("Audios"); / / create a folder mAudioManager = AudioManager.getInstance (dir); mAudioManager.setOnAudioStateListener (new AudioManager.AudioStateListener () {@ Override public void wellPrepared () {mHandler.sendEmptyMessage (MSG_AUDIO_PREPARED);}})) / / long button to prepare for recording includes start setOnLongClickListener (new OnLongClickListener () {@ Override public boolean onLongClick (View v) {/ / first determine whether there is recording and storage permission, then start recording without applying for permission int hasAudioPermission = ContextCompat.checkSelfPermission (mContext, Manifest.permission.RECORD_AUDIO); int hasStoragePermission = ContextCompat.checkSelfPermission (mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (hasAudioPermission = = PackageManager.PERMISSION_GRANTED & & hasStoragePermission = = PackageManager.PERMISSION_GRANTED) {mReady = true MAudioManager.prepareAudio ();} else {RxPermissions permissions = new RxPermissions ((FragmentActivity) mContext); Disposable disposable = permissions.request (Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribe (new Consumer () {@ Override public void accept (Boolean granted) {if (! granted) {ToastUtils.showShort ("recording and storage permissions are required to send voice messages");} return true;}}) } private static final int MSG_AUDIO_PREPARED = 0X110; private static final int MSG_VOICE_CHANGED = 0X111; private static final int MSG_DIALOG_DISMISS = 0X112; private static final int MSG_TIME_OUT = 0x113; private static final int UPDATE_TIME = 0x114; private boolean mThreadFlag = false; / / recording duration private float mTime; / / get the volume Runnable private Runnable mGetVoiceLevelRunnable = new Runnable () {@ Override public void run () {while (isRecording) {try {Thread.sleep (100); mTime + = 0.1f MHandler.sendEmptyMessage (MSG_VOICE_CHANGED); if (mTime > = AUDIO_RECORDER_MAX_TIME) {/ / if the recording time exceeds 60 seconds, while (! mThreadFlag) {/ / recording has finished recording and does not need to end again to avoid problems mDialogManager.dismissDialog (); mAudioManager.release (); if (audioFinishRecorderListener! = null) {/ / callback first, then Reset, otherwise the time in the callback is 0 audioFinishRecorderListener.onFinish (mTime, mAudioManager.getCurrentFilePath ()) MHandler.sendEmptyMessage (MSG_TIME_OUT);} mThreadFlag =! mThreadFlag;} isRecording = false;} else if (mTime > = AUDIO_RECORDER_COUNT_DOWN) {mHandler.sendEmptyMessage (UPDATE_TIME);}} catch (InterruptedException e) {e.printStackTrace ();}; private Handler mHandler = new Handler (new Handler.Callback () {@ Override public boolean handleMessage (Message msg) {switch (msg.what) {case MSG_AUDIO_PREPARED: mDialogManager.showRecordingDialog (); isRecording = true New Thread (mGetVoiceLevelRunnable). Start (); break; case MSG_VOICE_CHANGED: mDialogManager.updateVoiceLevel (mAudioManager.getVoiceLevel (7)); break; case MSG_DIALOG_DISMISS: mDialogManager.dismissDialog (); break; case MSG_TIME_OUT: reset (); break; case UPDATE_TIME: int countDown = (int) (AUDIO_RECORDER_MAX_TIME-mTime); mDialogManager.updateTime (countDown); break;} return true;}}) / * callback after recording * / public interface AudioFinishRecorderListener {/ * * @ param seconds * @ param filePath file * / void onFinish (float seconds, String filePath);} private AudioFinishRecorderListener audioFinishRecorderListener; public void setAudioFinishRecorderListener (AudioFinishRecorderListener listener) {audioFinishRecorderListener = listener;} android.media.AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener = new android.media.AudioManager.OnAudioFocusChangeListener () {@ Override public void onAudioFocusChange (int focusChange) {if (focusChange = = android.media.AudioManager.AUDIOFOCUS_LOSS) {audioManager.abandonAudioFocus (onAudioFocusChangeListener) }; public void myRequestAudioFocus () {audioManager.requestAudioFocus (onAudioFocusChangeListener, android.media.AudioManager.STREAM_MUSIC, android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);} @ Override public boolean onTouchEvent (MotionEvent event) {Logger.t ("AudioManager"). I ("x:" + event.getX () + "- Y:" + event.getY ()); switch (event.getAction ()) {case MotionEvent.ACTION_DOWN: mThreadFlag = false; isRecording = true; changeState (STATE_RECORDING); myRequestAudioFocus (); break Case MotionEvent.ACTION_MOVE: if (isRecording) {/ / judge whether you want to cancel if (event.getY () according to the coordinates of XBY.

< 0 && Math.abs(event.getY()) >

DISTANCE_Y_CANCEL) {changeState (STATE_WANT_TO_CANCEL);} else {changeState (STATE_RECORDING);}} break; case MotionEvent.ACTION_UP: / / if longClick does not trigger if (! mReady) {reset (); return super.onTouchEvent (event);} / / onLongClick is not ready, but prepared has been start / / so eliminate folder if (! isRecording | | mTime < 1.0f) {mDialogManager.tooShort (); mAudioManager.cancel () MHandler.sendEmptyMessageDelayed (MSG_DIALOG_DISMISS, 1000);} else if (mCurrentState = = STATE_RECORDING) {/ / normal end of recording mDialogManager.dismissDialog (); mAudioManager.release (); if (audioFinishRecorderListener! = null) {audioFinishRecorderListener.onFinish (mTime, mAudioManager.getCurrentFilePath ());}} else if (mCurrentState = = STATE_WANT_TO_CANCEL) {mDialogManager.dismissDialog (); mAudioManager.cancel ();} reset (); audioManager.abandonAudioFocus (onAudioFocusChangeListener); break;} return super.onTouchEvent (event) } / * restore state flag bit * / private void reset () {isRecording = false; mTime = 0; mReady = false; changeState (STATE_NORMAL);} / * change state * / private void changeState (int state) {if (mCurrentState! = state) {mCurrentState = state; switch (state) {case STATE_NORMAL: setText (R.string.audio_record_button_normal); break; case STATE_RECORDING: if (isRecording) {mDialogManager.recording () } setText (R.string.audio_record_button_recording); break; case STATE_WANT_TO_CANCEL: mDialogManager.wantToCancel (); setText (R.string.audio_record_button_cancel); break;}}

4 、 DialogStyle

True @ style/ActivityAnimTheme @ style/MenuStyle @ android:color/transparent true @ null true true @ style/ActivityDialogAnimation false @ anim/fade_in @ anim/fade_out

5 、 DialogLayout

6. The string used

Press and hold the speech to release the end release the finger to cancel the sending finger stroke, cancel the send release finger, cancel the recording time is too short

7. Use: the style of the button does not need to be written in the custom Button, so it is easy to use

AudioRecorderButton audioRecorderButton = findViewById (R.id.btn_audio_recorder); audioRecorderButton.setAudioFinishRecorderListener (new AudioRecorderButton.AudioFinishRecorderListener () {@ Override public void onFinish (float seconds, String filePath) {Logger.i (seconds + "seconds:" + filePath);}})

This is the end of the article on "how Android realizes the recording function of imitating Wechat". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it out for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report