Android 录音 有上滑取消录音,限制录音长度 ,录音动画以及仿微信播放动画效果

这是从公司项目里面的抽取出来的,开发过程中也碰到很多问题,基本上满足了一些需求,话不多少,看效果,上代码。。。。

               


1,给录音数据设置一个存放路径:

/**
     * 录音存放路径
     */
    public void initSoundData() {
        dataPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/AsRecrod/Sounds/";
        File folder = new File(dataPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        mMediaPlayUtil = MediaPlayUtil.getInstance();
    }


2,长按开始录音,需要设置view的onTouch事件,

在ACTION_DOWM中,初始化一些东西,开始录音,并开启录音计时和录音时的动画

ACTION_MOVE中,监听手指滑动的距离,往上滑动时提示取消录音

ACTION_UP中,如果没有超时,结束录音,显示录音

ACTION_CANCEL中,有的手机第一次录音时会提示开启录音权限,在点击开始权限时,会走到这里面,需要,清空数据,否则会出现录音失败,设置程序崩溃,很重要

/**
     * 录音的触摸监听
     */
    class VoiceTouch implements View.OnTouchListener {

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downY = motionEvent.getY();
                    mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record_pressed));
                    mTvNotice.setText("向上滑动取消发送");
                    mSoundData = dataPath + getRandomFileName() + ".amr";

                    // TODO 防止开权限后崩溃
                    if (mRecorder != null) {
                        mRecorder.reset();
                    } else {
                        mRecorder = new MediaRecorder();
                    }
                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
                    mRecorder.setOutputFile(mSoundData);
                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    try {
                        mRecorder.prepare();
                    } catch (IOException e) {
                        Log.i("recoder", "prepare() failed-Exception-" + e.toString());
                    }
                    try {
                        mRecorder.start();
                        mStartTime = System.currentTimeMillis();
                        mSoundLengthLayout.setVisibility(View.VISIBLE);
                        mTvTime.setText("0" + '"');
                        // TODO 开启定时器
                        mHandler.postDelayed(runnable, 1000);
                    } catch (Exception e) {
                        Log.i("recoder", "prepare() failed-Exception-"+e.toString());
                    }
                    initScaleAnim();
                    // TODO 录音过程重复动画
                    mScaleBigAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animation animation) {
                            if (mScaleLittleAnimation != null) {
                                mIvRecord.startAnimation(mScaleLittleAnimation);
                            }
                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {

                        }
                    });
                    mScaleLittleAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animation animation) {
                            if (mScaleBigAnimation != null) {
                                mIvRecord.startAnimation(mScaleBigAnimation);
                            }
                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {

                        }
                    });
                    mIvRecord.startAnimation(mScaleBigAnimation);

                    break;
                case MotionEvent.ACTION_UP:
                    if (!isStop) {
                        mEndTime = System.currentTimeMillis();
                        mTime = (int) ((mEndTime - mStartTime) / 1000);
                        stopRecord();
                        mIvRecord.setVisibility(View.VISIBLE);
                        try {
                            mVoiceData = StringUtil.encodeBase64File(mSoundData);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (isCanceled) {
                            deleteSoundFileUnSend();
                            mTvTime.setText("0" +'"' );
                            mTvNotice.setText("录音取消");
                            mRlVoiceLayout.setVisibility(View.GONE);
                        } else {
                            mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record));
                            mRlVoiceLayout.setVisibility(View.VISIBLE);
                            mTvTimeLengh.setText(mTime + "" +'"' );
                        }
                    }else{
                        mTvTime.setText("0");
                        mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record));
                        mTvNotice.setText("重新录音");
                    }
                    break;
                case MotionEvent.ACTION_CANCEL: // 首次开权限时会走这里,录音取消
                    Log.i("record_test","权限影响录音录音");
                    mHandler.removeCallbacks(runnable);
                    mSoundLengthLayout.setVisibility(View.GONE);

                    // TODO 这里一定注意,先release,还要置为null,否则录音会发生错误,还有可能崩溃
                    if (mRecorder != null) {
                        mRecorder.release();
                        mRecorder = null;
                        System.gc();
                    }
                    mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record));
                    mIvRecord.clearAnimation();
                    mTvNotice.setText("按住说话");
                    isCanceled = true;
                    mScaleBigAnimation = null;
                    mScaleLittleAnimation = null;

                    break;

                case MotionEvent.ACTION_MOVE: // 滑动手指
                    float moveY = motionEvent.getY();
                    if (downY - moveY > 100) {
                        isCanceled = true;
                        mTvNotice.setText("松开手指可取消录音");
                        mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record));
                    }
                    if (downY - moveY < 20) {
                        isCanceled = false;
                        mIvRecord.setImageDrawable(getResources().getDrawable(R.drawable.record_pressed));
                        mTvNotice.setText("向上滑动取消发送");
                    }
                    break;

            }
            return true;
        }

    }

3,定时器,这里采用handler,每隔一秒判断一下时间

// 定时器
    Runnable runnable = new Runnable() {

        @Override
        public void run() {
            // handler自带方法实现定时器
            try {
                long endTime = System.currentTimeMillis();
                int time = (int) ((endTime - mStartTime) / 1000);
                //mRlSoundLengthLayout.setVisibility(View.VISIBLE);
                mTvTime.setText(time + "" + '"');
                // 限制录音时间不长于两分钟
                if (time > 119) {
                    isStop = true;
                    mTime = time;
                    stopRecord();
                    Toast.makeText(MyActivity.this, "时间过长", Toast.LENGTH_SHORT).show();
                } else {
                    mHandler.postDelayed(this, 1000);
                    isStop = false;
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

4,结束录音,清空一些数据,防止对下次录音有影响

/**
     * 结束录音
     */
    public void stopRecord() {
        mIvRecord.clearAnimation();
        mScaleBigAnimation = null;
        mScaleLittleAnimation = null;
        if (mTime < 1) {
            deleteSoundFileUnSend();
            isCanceled = true;
            Toast.makeText(MyActivity.this, "录音时间太短,长按开始录音", Toast.LENGTH_SHORT).show();
        } else {
            mTvNotice.setText("录音成功");
            // 不加  "" 空串 会出  Resources$NotFoundException 错误
            mTvTime.setText(mTime + "" + '"');
            Log.i("record_test","录音成功");

        }
        //mRecorder.setOnErrorListener(null);
        try {
            mRecorder.stop();
            mRecorder.reset();
            mRecorder.release();
        } catch (Exception e) {
            Log.i("recoder", "stop() failed");
            isCanceled = true;
            mIvRecord.setVisibility(View.VISIBLE);
            mTvTime.setText("");
            Toast.makeText(MyActivity.this, "录音发生错误,请重新录音", Toast.LENGTH_LONG).show();
            Log.i("record_test","录音发生错误");
        }
        mHandler.removeCallbacks(runnable);
        if (mRecorder != null) {
            mRecorder = null;
            System.gc();
        }

    }

5,播放录音,这里是仿微信的效果,凑合凑合吧

// TODO 播放录音
        mRlVoiceLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mMediaPlayUtil.isPlaying()) {
                    mMediaPlayUtil.stop();
                    mImageAnim.stop();
                    mIvVoice.setVisibility(View.VISIBLE);
                    mIvVoiceAnim.setVisibility(View.GONE);
                } else {
                    startAnim();
                    mMediaPlayUtil.play(StringUtil.decoderBase64File(mVoiceData));
                }
            }
        });

/**
     * 语音播放效果
     *
     */
    public void startAnim() {

        mImageAnim = (AnimationDrawable) mIvVoiceAnim.getBackground();
        mIvVoiceAnim.setVisibility(View.VISIBLE);
        mIvVoice.setVisibility(View.GONE);
        mImageAnim.start();
        mMediaPlayUtil.setPlayOnCompleteListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                mIvVoice.setVisibility(View.VISIBLE);
                mIvVoiceAnim.setVisibility(View.GONE);
            }
        });
    }

6,不要忘了添加权限

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

7,源码下载地址: http://download.csdn.net/detail/qq55214/9456371



  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值