一个BUTTON,实现点击播放录音,长按录音
2017-02-19 15:30
204 查看
因为毕业设计里有需要用到录音的功能,但是又要求界面比较小巧,所以思考了许久,相出个这么办法,让一个BUTTON把播放和录音的功能全部实现(当然,其他的也可以——。——~)
1.点击的话则播放/停止播放录音
2.长按则开始录音,手指离开则停止录音
为了实现上面的效果,我们首先需要识别是点击还是长按,并且得知长按模式下按下和离开的时间。用设置setOnTouchListener的方式的话,自然可以实现,只要在按下后设置计时器就OK了,但是安卓里GestureDetector这个类提供了onSingleTapUp()和onLongPress()这两个方法帮助我们获取到简单的点击和长按事件,下面我们就测试如何利用这两个方法来分辨点击和长按模式吧
不懂GestureDetector请手搓用户手势检测-GestureDetector使用详解
首先继承SimpleOnGestureListener并重写上面提到的两个方法
点击
长按并得知手指离开的时间
很轻易的辨别出了两种模式,并且得知何时结束录音,那么就可以像这么写了,在函数内直接添加录音相关的内容即可
有人可能会问,上面的这部分代码为什么不把判断ACTION_UP放在前面呢?
0=ACTION_DOWN 1=ACTION_UP 2=ACTION_MOVE
可以看到在传递过来了几次ACTION_MOVE后才触发的onSingleTapUp,所以我不赞成把判断写在前面,因为有时会有意料之外的结果,尤其是你打算在if判断句里return的时候
RecordUtils类
用的话,就这么用
也不要忘了添加权限
1.点击的话则播放/停止播放录音
2.长按则开始录音,手指离开则停止录音
为了实现上面的效果,我们首先需要识别是点击还是长按,并且得知长按模式下按下和离开的时间。用设置setOnTouchListener的方式的话,自然可以实现,只要在按下后设置计时器就OK了,但是安卓里GestureDetector这个类提供了onSingleTapUp()和onLongPress()这两个方法帮助我们获取到简单的点击和长按事件,下面我们就测试如何利用这两个方法来分辨点击和长按模式吧
不懂GestureDetector请手搓用户手势检测-GestureDetector使用详解
两个模式的判断
好了,请看关键代码和结果首先继承SimpleOnGestureListener并重写上面提到的两个方法
class RecordGesture extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { Log.v("RecordGesture","onSingleTapUp"); return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { Log.v("RecordGesture","onLongPress"); super.onLongPress(e); } }然后用它来设置触摸监听,同时省略一堆东西
private RecordGesture gesture; private GestureDetector detector;省略。。。
gesture = new RecordGesture(); detector = new GestureDetector(context, gesture); setOnTouchListener(this);省略。。。
@Override public boolean onTouch(View v, MotionEvent event) { detector.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP) { Log.v("RecordGesture","ACTION_UP"); } return true; }下面附上结果图
点击
长按并得知手指离开的时间
很轻易的辨别出了两种模式,并且得知何时结束录音,那么就可以像这么写了,在函数内直接添加录音相关的内容即可
@Override public boolean onTouch(View v, MotionEvent event) { detector.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP && isRecording) { stopSoundRecord(); } return true; } class RecordGesture extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { Log.v("RecordGesture","onSingleTapUp"); if (isPlaying) { stopPlayRecord(); } else { startPlayRecord(); } return super.onSingleTapUp(e); }
@Override public void onLongPress(MotionEvent e) { Log.v("RecordGesture","onLongPress"); startSoundRecord(); super.onLongPress(e); } }
有人可能会问,上面的这部分代码为什么不把判断ACTION_UP放在前面呢?
detector.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP) { Log.v("RecordGesture","ACTION_UP"); }让我们在重写的onTouch里添加这句代码,然后触发点击事件看看
Log.v("RecordGesture",event.getAction()+" "+System.currentTimeMillis());
0=ACTION_DOWN 1=ACTION_UP 2=ACTION_MOVE
可以看到在传递过来了几次ACTION_MOVE后才触发的onSingleTapUp,所以我不赞成把判断写在前面,因为有时会有意料之外的结果,尤其是你打算在if判断句里return的时候
项目关键代码
这章博客我是准备写录音来着吧。。。。好像是,不过网上录音的博客太多了,就不多讲了,还是直接贴代码吧,100多行简单了事import android.content.Context; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Vibrator; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import java.io.IOException; import static android.content.Context.VIBRATOR_SERVICE; import static android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED; import static android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED; import static com.sy.audiorecord.audiorecord.RecordUtils.durationToStr; import static com.sy.audiorecord.audiorecord.RecordUtils.getRecordDuration; public class SoundRecord extends Button implements View.OnTouchListener { private RecordGesture gesture; private GestureDetector detector; private Vibrator vibrator;//振动器 private boolean isRecording = false;//是否正在录音 private boolean isPlaying = false;//是否正在播放录音 private MediaPlayer player = null;//媒体播放器 private MediaRecorder recorder = null;//媒体录音器 private String filePath;//文件路径 private int maxDuration = 0;//录音最大时间限制 private long max_filesize_bytes = 0;//录音文件最大大小限制 public void setMaxDuration(int maxDuration) { this.maxDuration = maxDuration; } public void setMax_filesize_bytes(long max_filesize_bytes) { this.max_filesize_bytes = max_filesize_bytes; } public void setFilePath(String filePath) { this.filePath = filePath; setText(durationToStr(getRecordDuration(this.filePath))); } public SoundRecord(Context context) { super(context, null); } public SoundRecord(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { vibrator = (Vibrator) context.getSystemService(VIBRATOR_SERVICE); gesture = new RecordGesture(); detector = new GestureDetector(context, gesture); setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { detector.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP && isRecording) { stopSoundRecord(); } return true; } class RecordGesture extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { if (isPlaying) { stopPlayRecord(); } else { startPlayRecord(); } return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { startSoundRecord(); super.onLongPress(e); } } private void beforePlayStart() { vibrator.vibrate(100); } private void afterPlayEnd() { vibrator.vibrate(100); } private void startPlayRecord() { try { player = new MediaPlayer(); player.setDataSource(filePath); player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { stopPlayRecord(); } }); player.prepare(); beforePlayStart(); player.start(); isPlaying = true; } catch (IOException e1) { e1.printStackTrace(); } } private void stopPlayRecord() { player.stop(); player.release(); player = null; isPlaying = false; afterPlayEnd(); } private void beforeRecordStart() { vibrator.vibrate(100); } private void afterRecordEnd() { vibrator.vibrate(100); setText(durationToStr(getRecordDuration(filePath))); } private void startSoundRecord() { recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); recorder.setOutputFile(filePath); recorder.setMaxDuration(maxDuration); recorder.setMaxFileSize(max_filesize_bytes); recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() { @Override public void onInfo(MediaRecorder mr, int what, int extra) { if (MEDIA_RECORDER_INFO_MAX_DURATION_REACHED == what || MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED == what) {stopSoundRecord(); } } }); try { recorder.prepare(); beforeRecordStart(); recorder.start(); isRecording = true; } catch (IOException e1) { e1.printStackTrace(); } } private void stopSoundRecord() { recorder.release(); recorder = null; isRecording = false; afterRecordEnd(); }}
RecordUtils类
public class RecordUtils { public static int getRecordDuration(String filePath) { int duration = -1; //如果文件不存在就返回-1 File file = new File(filePath); if (!file.exists()) return duration; //如果文件存在但是是流媒体直播的内容则也会返回-1 MediaPlayer player = new MediaPlayer(); try { player.setDataSource(filePath); player.prepare(); duration = player.getDuration(); player.reset(); player.release(); } catch (IOException e) { e.printStackTrace(); } return duration; } public static String durationToStr(int duration) { //如果传进来的时长为-1则返回代表没有内容的字符串"..:.." if (-1 == duration) return "..:.."; //时长不为1的话,则按"分:秒"的字符串形式组合字符串传出 StringBuilder builder = new StringBuilder(); float sumSecond = duration / 1000; int minute = (int) (sumSecond / 60); int second = (int) (sumSecond % 60); builder.append(minute).append(":").append(second); return builder.toString(); } }
用的话,就这么用
record= (SoundRecord) findViewById(R.id.record); record.setFilePath(Environment.getExternalStorageDirectory().getPath()+ File.separatorChar+"123"+".mp3");
也不要忘了添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.VIBRATE" />这个是振动器的权限
相关文章推荐
- java实现一个录音播放的功能
- Runtime_实现计算一个Button被点击次数
- UIWebView中视频点击链接直接全屏播放而不是点击一个播放按钮的实现方法
- 使用jquery点击一个实现button或连接,进行以下div显示,在点击隐藏
- xcode简单教程,实现一个button点击事件
- 点击button按钮后,启动一个实现鼠标拖动另一个button的线程 (JFrame/C# WinForm)
- Android ImageButton 如何实现一个点击效果
- 有一个table表格,选中某一行后,点击“查看(button)”按钮可以实现对该行内容的显示
- C#怎么通过一个按钮Button,实现点击这个按钮可以打开一个文件或者文件夹?
- 有一个table表格,选中某一行后,点击“查看(button)”按钮可以实现对该行内容的显示
- window里面点击一个button按钮实现页面跳转???
- 在页面中,我们经常看到,一个button按钮,如果属标点击,就会触发一个窗口的显示,如果二次点击并可以隐藏,那么如何通过JAVA配合html来实现这一功能呢?
- 实现一个录音播放功能的app(ios)
- 关于相同页面用一个页面实现,点击datalist中Button按钮出现“回发或回调参数无效......”
- Unity中UGUI实现点击改按钮播放一个音效
- 网页上实现一个在线录音的功能
- 点击一个button按钮使窗体2显示在窗体1中
- 折叠菜单(怎么实现点击一个打开,另一个收起)
- 同一页面中实现点击其中一个iframe中的链接后,将链接内容显示到另一iframe
- CSoundBase实现录音与播放