模仿微信的按住录音功能

我把整个逻辑封装到一个Button里了,可以直接使用这个Button,当按住时会开始录音,当手指移到Button外时取消录音,该Button还向外暴露了一个Finish接口,录音完成时调用这个接口,具体使用方法看代码吧。

效果如下:

  1 package demo.com;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 
  6 import android.app.Dialog;
  7 import android.content.Context;
  8 import android.content.DialogInterface;
  9 import android.content.DialogInterface.OnDismissListener;
 10 import android.media.MediaRecorder;
 11 import android.os.Handler;
 12 import android.os.Message;
 13 import android.util.AttributeSet;
 14 import android.view.Gravity;
 15 import android.view.MotionEvent;
 16 import android.view.ViewGroup;
 17 import android.view.WindowManager.LayoutParams;
 18 import android.widget.Button;
 19 import android.widget.ImageView;
 20 import android.widget.Toast;
 21 
 22 public class RecordButton extends Button {
 23 
 24     public RecordButton(Context context) {
 25         super(context);
 26         init();
 27     }
 28 
 29     public RecordButton(Context context, AttributeSet attrs, int defStyle) {
 30         super(context, attrs, defStyle);
 31         init();
 32     }
 33 
 34     public RecordButton(Context context, AttributeSet attrs) {
 35         super(context, attrs);
 36         init();
 37     }
 38 
 39     public void setSavePath(String path) {
 40         mFileName = path;
 41     }
 42 
 43     public void setOnFinishedRecordListener(OnFinishedRecordListener listener) {
 44         finishedListener = listener;
 45     }
 46 
 47     private String mFileName = null;
 48 
 49     private OnFinishedRecordListener finishedListener;
 50 
 51     private static final int MIN_INTERVAL_TIME = 2000;// 2s
 52     private long startTime;
 53 
 54     private Dialog recordIndicator;
 55 
 56     private static int[] res = { R.drawable.mic_2, R.drawable.mic_3,
 57             R.drawable.mic_4, R.drawable.mic_5 };
 58 
 59     private static ImageView view;
 60 
 61     private MediaRecorder recorder;
 62 
 63     private ObtainDecibelThread thread;
 64 
 65     private Handler volumeHandler;
 66 
 67     private void init() {
 68         volumeHandler = new ShowVolumeHandler();
 69     }
 70 
 71     @Override
 72     public boolean onTouchEvent(MotionEvent event) {
 73 
 74         if (mFileName == null)
 75             return false;
 76 
 77         int action = event.getAction();
 78 
 79         switch (action) {
 80         case MotionEvent.ACTION_DOWN:
 81             initDialogAndStartRecord();
 82             break;
 83         case MotionEvent.ACTION_UP:
 84             finishRecord();
 85             break;
 86         case MotionEvent.ACTION_CANCEL:// 当手指移动到view外面,会cancel
 87             cancelRecord();
 88             break;
 89         }
 90 
 91         return true;
 92     }
 93 
 94     private void initDialogAndStartRecord() {
 95 
 96         startTime = System.currentTimeMillis();
 97         recordIndicator = new Dialog(getContext(),
 98                 R.style.like_toast_dialog_style);
 99         view = new ImageView(getContext());
100         view.setImageResource(R.drawable.mic_2);
101         recordIndicator.setContentView(view, new LayoutParams(
102                 ViewGroup.LayoutParams.MATCH_PARENT,
103                 ViewGroup.LayoutParams.MATCH_PARENT));
104         recordIndicator.setOnDismissListener(onDismiss);
105         LayoutParams lp = recordIndicator.getWindow().getAttributes();
106         lp.gravity = Gravity.CENTER;
107 
108         startRecording();
109         recordIndicator.show();
110     }
111 
112     private void finishRecord() {
113         stopRecording();
114         recordIndicator.dismiss();
115 
116         long intervalTime = System.currentTimeMillis() - startTime;
117         if (intervalTime < MIN_INTERVAL_TIME) {
118             Toast.makeText(getContext(), "时间太短!", Toast.LENGTH_SHORT).show();
119             File file = new File(mFileName);
120             file.delete();
121             return;
122         }
123 
124         if (finishedListener != null)
125             finishedListener.onFinishedRecord(mFileName);
126     }
127 
128     private void cancelRecord() {
129         stopRecording();
130         recordIndicator.dismiss();
131 
132         Toast.makeText(getContext(), "取消录音!", Toast.LENGTH_SHORT).show();
133         File file = new File(mFileName);
134         file.delete();
135     }
136 
137     private void startRecording() {
138         recorder = new MediaRecorder();
139         recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
140         recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
141         recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
142         recorder.setOutputFile(mFileName);
143 
144         try {
145             recorder.prepare();
146         } catch (IOException e) {
147             e.printStackTrace();
148         }
149 
150         recorder.start();
151         thread = new ObtainDecibelThread();
152         thread.start();
153 
154     }
155 
156     private void stopRecording() {
157         if (thread != null) {
158             thread.exit();
159             thread = null;
160         }
161         if (recorder != null) {
162             recorder.stop();
163             recorder.release();
164             recorder = null;
165         }
166     }
167 
168     private class ObtainDecibelThread extends Thread {
169 
170         private volatile boolean running = true;
171 
172         public void exit() {
173             running = false;
174         }
175 
176         @Override
177         public void run() {
178             while (running) {
179                 try {
180                     Thread.sleep(200);
181                 } catch (InterruptedException e) {
182                     e.printStackTrace();
183                 }
184                 if (recorder == null || !running) {
185                     break;
186                 }
187                 int x = recorder.getMaxAmplitude();
188                 if (x != 0) {
189                     int f = (int) (10 * Math.log(x) / Math.log(10));
190                     if (f < 26)
191                         volumeHandler.sendEmptyMessage(0);
192                     else if (f < 32)
193                         volumeHandler.sendEmptyMessage(1);
194                     else if (f < 38)
195                         volumeHandler.sendEmptyMessage(2);
196                     else
197                         volumeHandler.sendEmptyMessage(3);
198 
199                 }
200 
201             }
202         }
203 
204     }
205 
206     private OnDismissListener onDismiss = new OnDismissListener() {
207 
208         @Override
209         public void onDismiss(DialogInterface dialog) {
210             stopRecording();
211         }
212     };
213 
214     static class ShowVolumeHandler extends Handler {
215         @Override
216         public void handleMessage(Message msg) {
217             view.setImageResource(res[msg.what]);
218         }
219     }
220 
221     public interface OnFinishedRecordListener {
222         public void onFinishedRecord(String audioPath);
223     }
224 
225 }

 

整个项目的下载地址:

https://files.cnblogs.com/coding-way/record_button.zip

posted @ 2013-01-28 11:41  周柯文  阅读(7773)  评论(1编辑  收藏  举报