一个BUTTON,实现点击播放录音,长按录音

 

因为毕业设计里有需要用到录音的功能,但是又要求界面比较小巧,所以思考了许久,相出个这么办法,让一个BUTTON把播放和录音的功能全部实现(当然,其他的也可以——。——~)

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" />这个是振动器的权限
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值