为了账号安全,请及时绑定邮箱和手机立即绑定

Audio整合后测试出错,希望hyman老师和同学们看下

在audio整合章节的测试,log抛出一个异常,

异常1
E/InputEventReceiver(17950): Exception dispatching input event.
 E/MessageQueue-JNI(17950): Exception in MessageQueue callback: handleReceiveCallback
 java.lang.NullPointerException
 at com.imoc_recorder.view.AudioManager.release(AudioManager.java:98)
 at com.imoc_recorder.view.AudioManager.cancel(AudioManager.java:103)
 at com.imoc_recorder.view.AudioRecorderButton.onTouchEvent(AudioRecorderButton.java:154)
 异常2
/AndroidRuntime(17950): FATAL EXCEPTION: main
 E/AndroidRuntime(17950): java.lang.NullPointerException
at com.imoc_recorder.view.AudioManager.release(AudioManager.java:98)
 at com.imoc_recorder.view.AudioManager.cancel(AudioManager.java:103)
 at com.imoc_recorder.view.AudioRecorderButton.onTouchEvent(AudioRecorderButton.java:154)
 两个异常都是在同一个地方出错
 AudioRecorderButton.java->onTouchEvent(MotionEvent event)->if (!isRecording||mTime<0.6f) 
 ->mAudioManager.cancel();->release();->mMediaRecorder.stop();
我上网查了下没发现什么错误,希望老师和同学们指点,为什么会错,跟老师的代码一样阿
其实我是长按,不知道为什么会进到这里

public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        
//        try {
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                changeState(STATE_RECORDING);
                break;

            case MotionEvent.ACTION_MOVE:
                if (isRecording) {
                    if (wantToCancel(x,y)) {
                        changeState(STATE_WANT_TO_CANCEL);
                    }else {
                        changeState(STATE_RECORDING);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!mReady) {
                    reset();
                    return super.onTouchEvent(event);
                }
                if (!isRecording||mTime<0.6f) {//时间短,还没有来得及repared
                    mDailogManager.tooShort();
                    mAudioManager.cancel();
                    mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);//1.3秒后关闭tooshort
                }else    if (mCurState==STATE_RECORDING) {//正常录制结束
                    //release
                    mDailogManager.dimissDialog();
                    mAudioManager.release();
                    //callbackToAct
                    if (mListener != null) {
                        mListener.onFinish(mTime, mAudioManager.getCurrentFilePath());
                    }
                }else if (mCurState==STATE_WANT_TO_CANCEL) { 
                    //cancel
                    mDailogManager.dimissDialog();
                    mAudioManager.cancel();
                }
                reset();
                break;
                
                
       public void release() {
            mMediaRecorder.stop();
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
        public void cancel() {
            release();
            if (mCurrentFilePath != null) {
                File file = new File(mCurrentFilePath);
                file.delete();
                mCurrentFilePath = null;
        }
    }


正在回答

5 回答

我看你是在release()方法里面抛出的空指针,错误行应该就一个对象mMediaRecorder吧,你看看你是不是cancel还是某个方法里面误把mMediaRecorder置null了。



0 回复 有任何疑惑可以回复我~

不给源码不知道什么心态。这么长时间的视频让我们开着视频对代码找错我真是醉了。

0 回复 有任何疑惑可以回复我~

同样的问题。不知道怎么回事。

0 回复 有任何疑惑可以回复我~
mport com.example.imoc_recorder.R;
import com.imoc_recorder.view.AudioManager.AudioStateListener;

import android.R.integer;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class AudioRecorderButton extends Button implements AudioStateListener {
    
    private final int DISTANCE_Y_CANCEL = 50; //y方向的移动距离
    private static final int STATE_NORNMAL =1;
    private static final int STATE_RECORDING =2;
    private static final int STATE_WANT_TO_CANCEL =3;
    
    private int mCurState = STATE_NORNMAL;
    private boolean isRecording=false; //已经开始录音
    
    private DailogManager mDailogManager;
    
    private AudioManager mAudioManager;
    
    private float mTime=0;
    //是否触发longclick
    private boolean mReady;
    
    public AudioRecorderButton(Context context) {
        this(context,null);
    }
    public AudioRecorderButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        mDailogManager = new DailogManager(getContext());
        setOnLongClickListener(new OnLongClickListener() {
            
            @Override
            public boolean onLongClick(View v) {
                mReady = true;
                mAudioManager.prepareAudio();
                return false;
            }
        });
        
        String dir = Environment.getExternalStorageDirectory()+"/imooc_recorder_audios";
        mAudioManager = AudioManager.getInstance(dir);
        mAudioManager.setOnAudioStateListener(this); //注册回调
                
            }
    
    //录音完成后的回调
    public interface AudioFinishRecorderListener {
        void onFinished(float seconds,String filePath);
    }
    
    private AudioFinishRecorderListener mListener;
    
    public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener) {
        mListener = listener;
    }
    
    @Override
    public void wellPrepared() {
        mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
    }
    /*
     * 获取音量大小
     */
    private Runnable mGetVoiceLevelRunnable=new Runnable() {
        
        @Override
        public void run() {
            while (isRecording) {
                
                    try {
                        Thread.sleep(100);
                        mTime+=0.1f;
                        mHandler.sendEmptyMessage(MSG_VOICE_CHANGE);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    
                
            }
        }
    };
    
    private static final int MSG_AUDIO_PREPARED = 0X110;
    private static final int MSG_VOICE_CHANGE = 0X111;
    private static final int MSG_DIALOG_DIMISS = 0X112;
    
    private  Handler mHandler = new Handler()
    {
        

        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case MSG_AUDIO_PREPARED:
                // 正真显示dialog在audio end prepared以后
                mDailogManager.showRecordingDialog();
                isRecording = true;
                //开启线程获取音量
                new Thread(mGetVoiceLevelRunnable).start();
                break;
            case MSG_VOICE_CHANGE:
                mDailogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(7));
                break;
            case MSG_DIALOG_DIMISS:
                mDailogManager.dimissDialog();
                break;
            }
        };
    };
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        
//        try {
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                changeState(STATE_RECORDING);
                break;

            case MotionEvent.ACTION_MOVE:
                if (isRecording) {
                    if (wantToCancel(x,y)) {
                        changeState(STATE_WANT_TO_CANCEL);
                    }else {
                        changeState(STATE_RECORDING);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!mReady) {
                    reset();
                    return super.onTouchEvent(event);
                }
                if (!isRecording||mTime<0.6f) {//时间短,还没有来得及repared
                    mDailogManager.tooShort();
                    mAudioManager.cancel();
                    mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);//1.3秒后关闭tooshort
                }else    if (mCurState==STATE_RECORDING) {//正常录制结束
                    //release
                    mDailogManager.dimissDialog();
                    mAudioManager.release();
                    //callbackToAct
                    if (mListener != null) {
                        mListener.onFinished(mTime, mAudioManager.getCurrentFilePath());
                    }
                }else if (mCurState==STATE_WANT_TO_CANCEL) { 
                    //cancel
                    mDailogManager.dimissDialog();
                    mAudioManager.cancel();
                }
                reset();
                break;
            }
//        } catch (Exception e) {
//            System.out.println("1111111111111111111111111111");
//            e.printStackTrace();
//        }
        
        return super.onTouchEvent(event);
        
    }
        //恢复标志位
    private void reset() {

        isRecording = false;
        changeState(STATE_NORNMAL);
        mTime = 0;
        mReady = false;
    }
    private boolean wantToCancel(int x, int y) {
        if (x<0 || x>getWidth()) {
            return true ;
        }
        if(y<-DISTANCE_Y_CANCEL || y>getHeight()+DISTANCE_Y_CANCEL)
        {
            return true;
        }
        return false;
    }
    private void changeState(int state) {//state是将要边车的状态
        if (mCurState!=state) {
            mCurState = state;
            switch (state) {
            case STATE_NORNMAL:
                setBackgroundResource(R.drawable.btn_recorder_normal);
                setText(R.string.str_recorder_normal);
                break;
            case STATE_RECORDING:
                setBackgroundResource(R.drawable. btn_recording);
                setText(R.string.str_recorder_recording);
                if (isRecording) {
                
                    mDailogManager.recording();
                }
                break;
            case STATE_WANT_TO_CANCEL:
                setBackgroundResource(R.drawable.btn_recording);
                setText(R.string.str_recorder_cancel);
                
                mDailogManager.wantToCancel();
                break;
            }
        }
    }

    

}


0 回复 有任何疑惑可以回复我~

我认真的排查过,只有release()里置空过

package com.imoc_recorder.view;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

import android.R.integer;
import android.media.MediaRecorder;
import android.util.Log;

public class AudioManager {
    
    private MediaRecorder mMediaRecorder;
    private String mDir;
    private String mCurrentFilePath;
    private boolean isPrepared;
    
    private static AudioManager mInstance;
    private AudioManager(String dir){
        mDir = dir;
    }
    /*
     * 回调准备完毕
     */
    public  interface AudioStateListener {
        void wellPrepared();
    }
    
    public AudioStateListener mListener;
    
    public void  setOnAudioStateListener(AudioStateListener listener) {
        mListener = listener;
    }
    public static  AudioManager getInstance(String dir) {
        if (mInstance == null) {
            synchronized (AudioManager.class) {
                if (mInstance == null) {
                    mInstance = new AudioManager(dir);
                }
            }
        }
        return mInstance;
    }
    
    //准备
    public void  prepareAudio() {
        try {
            isPrepared = false;
            
            File dir = new File(mDir);
            if (!dir.exists()) {
                dir.mkdirs();
                
                String fileName = generateFileName();
                File file = new File(dir,fileName);
                mCurrentFilePath = file.getAbsolutePath();
                
                mMediaRecorder = new MediaRecorder();
                //设置输出文件
                mMediaRecorder.setOutputFile(file.getAbsolutePath());
                //设置MediaRecorder的音频源为麦克风
                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                //设置音频的格式
                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
                //设置音频编码为amr
                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mMediaRecorder.prepare();
                mMediaRecorder.start();
                isPrepared = true;
    
                if (mListener != null) {
                    mListener.wellPrepared();
                }
            }
        } catch (Exception e) {
            
            e.printStackTrace();
        }
    }
    //随机生成文件名
    private String generateFileName() {
        return UUID.randomUUID().toString()+".amr";
    }

    public int getVoiceLevel(int maxLevel) {
        if(isPrepared)
        {
            try {
                return maxLevel*mMediaRecorder.getMaxAmplitude()/32768+1; //音频的最大振幅1!32767~1
            } catch (Exception e) {
            
                e.printStackTrace();
            }
        }
        return 1;
    }
    
    public void release() {
        mMediaRecorder.stop();
        mMediaRecorder.release();
//        mMediaRecorder = null;
    }
    public void cancel() {
        release();
        if (mCurrentFilePath != null) {
            File file = new File(mCurrentFilePath);
            file.delete();
            mCurrentFilePath = null;
        }
    }
    public String getCurrentFilePath() {
        return mCurrentFilePath;
    }

    
}


0 回复 有任何疑惑可以回复我~
#1

安静的y

try 下面if 的括号不对吧
2015-05-14 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
Android-仿微信语音聊天
  • 参与学习       43200    人
  • 解答问题       220    个

结合自定义View和API,Dialog管理等实现实现微信语音

进入课程

Audio整合后测试出错,希望hyman老师和同学们看下

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信