用于录制 30 秒声音的 SeekBar - handleReceiveCallback 错误

SeekBar for recording 30 second sound - handleReceiveCallback error

我一直在尝试让用户录制长达 30 秒的声音,并使用 SeekBar 来指示他们到目前为止录制了多少。我从各种在线说明中拼凑了一些代码,但我不断收到 NPE 和 "Exception in MessageQueue callback: handleReceiveCallback"/"Exception dispatching input event" 错误。我不确定如何解释这个或我做错了什么。通过日志标签,我可以看出它到达了 StartRecording(),然后在调用 Handler 来跟踪记录长度时抛出异常。任何人都可以看到问题吗?代码如下:

内部录音机class:

import java.io.File;
import java.io.IOException;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;


public class AudioRecorder {

    private static final String LOG_TAG = "AudioRecordTest";
    private String fileName = Environment.getExternalStorageDirectory()+"/audio"+System.currentTimeMillis()+".3gp";
    private static MediaRecorder mRecorder;
    private static MediaPlayer   mPlayer;
    public boolean isRecording;
    public boolean isPlaying;
    int recordTime;
    Handler handler;

    public void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();
        }

    }

    public void onPlay(boolean start) {
        if (start) {
            startPlaying();
        } else {
            stopPlaying();
        }

    }

    public void startPlaying() {
        mPlayer = new MediaPlayer();
        try {
            mPlayer.setDataSource(fileName);
            mPlayer.prepare();
            mPlayer.start();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }
        isPlaying = true;
    }

    public void stopPlaying() {
        mPlayer.release();
        mPlayer = null;
        isPlaying = false;
    }

    public void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(fileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recordTime = 0;

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }

        Log.w("LCC", "Start playing made it this far! 1!");

        mRecorder.start();
        isRecording = true;
        handler.post(UpdateRecordTime);
    }

    public void stopRecording() {
        mRecorder.stop();
        mRecorder.reset();
        mRecorder = null;
        isRecording = false;
        handler.removeCallbacks(UpdateRecordTime);
    }

    public void playSound(Context c){
        if (mPlayer == null) {
            Uri uri = Uri.parse(fileName);
            mPlayer = MediaPlayer.create(c, uri);

            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                public void onCompletion(MediaPlayer mp) {
                    stopPlayer();
                }
            });
        }

        mPlayer.start();
    }

    public void stopPlayer() {
        if (mPlayer != null) {
            mPlayer.release();
            mPlayer = null;
        }
    }

    Runnable UpdateRecordTime = new Runnable(){
         public void run(){
             if(isRecording){ 
                  recordTime++;
                  // Delay 1s before next call      
                  handler.postDelayed(this, 1000);
                }
         }
    };

    public int getCurrentPosition(){
        return recordTime;
    };
}

在 AudioRecorderActivity 里面 class:

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;

public class AudioRecorderActivity extends ActionBarActivity {
    private AudioRecorder mRecorder = new AudioRecorder();
    //private View mPlayButton;
    //private View mStopButton;
    //private View mRecordButton;
    private View mRecordButton;
    private SeekBar mSeekBar;
    private boolean isRecording;


    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //requestWindowFeature(Window.FEATURE_NO_TITLE);
        //getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                                       // WindowManager.LayoutParams.FLAG_FULLSCREEN);        
        setContentView(R.layout.activity_record);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);

        mSeekBar = (SeekBar)findViewById(R.id.SeekBar);
        mSeekBar.setMax(30);

        mRecordButton = findViewById(R.id.recordPlayButton);
        mRecordButton.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                switch(event.getAction()){
                 case MotionEvent.ACTION_DOWN:
                     mRecorder.onRecord(true);
                     isRecording = true;

                    final Handler mHandler = new Handler();
                    final Runnable mRunnable = new Runnable() {

                        @Override
                        public void run() {
                            if(mRecorder.isRecording){
                                int mCurrentPosition = mRecorder.getCurrentPosition() / 1000;
                                mSeekBar.setProgress(mCurrentPosition);
                            }
                            mHandler.postDelayed(this, 1000);
                        }
                    };

                     break;
                 case MotionEvent.ACTION_UP:
                     mRecorder.stopRecording();
                     isRecording = false;
                     break;
                }
                return false;
            }
        });

如有任何帮助,我们将不胜感激。谢谢!!

编辑:这是确切的错误(每当我按下录制按钮时都会出现两组)

02-03 17:17:28.189: W/LCC(3757): Start playing made it this far! 1!
02-03 17:17:28.579: E/InputEventReceiver(3757): Exception dispatching input event.
02-03 17:17:28.579: E/MessageQueue-JNI(3757): Exception in MessageQueue callback: handleReceiveCallback
02-03 17:17:28.599: E/MessageQueue-JNI(3757): java.lang.NullPointerException
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.littlecloudcollective.waves.AudioRecorder.startRecording(AudioRecorder.java:80)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.littlecloudcollective.waves.AudioRecorder.onRecord(AudioRecorder.java:28)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.littlecloudcollective.waves.AudioRecorderActivity.onTouch(AudioRecorderActivity.java:43)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.View.dispatchTouchEvent(View.java:7229)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2177)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1482)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.app.Activity.dispatchTouchEvent(Activity.java:2469)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:260)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2125)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.View.dispatchPointerEvent(View.java:7414)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3523)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3455)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4565)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4543)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4647)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.os.MessageQueue.nativePollOnce(Native Method)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.os.MessageQueue.next(MessageQueue.java:125)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.os.Looper.loop(Looper.java:124)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at android.app.ActivityThread.main(ActivityThread.java:4963)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at java.lang.reflect.Method.invokeNative(Native Method)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at java.lang.reflect.Method.invoke(Method.java:511)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
02-03 17:17:28.599: E/MessageQueue-JNI(3757):   at dalvik.system.NativeStart.main(Native Method)
02-03 17:17:28.599: D/AndroidRuntime(3757): Shutting down VM
02-03 17:17:28.599: W/dalvikvm(3757): threadid=1: thread exiting with uncaught exception (group=0x41104438)
02-03 17:17:28.609: E/AndroidRuntime(3757): FATAL EXCEPTION: main
02-03 17:17:28.609: E/AndroidRuntime(3757): java.lang.NullPointerException
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.littlecloudcollective.waves.AudioRecorder.startRecording(AudioRecorder.java:80)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.littlecloudcollective.waves.AudioRecorder.onRecord(AudioRecorder.java:28)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.littlecloudcollective.waves.AudioRecorderActivity.onTouch(AudioRecorderActivity.java:43)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.View.dispatchTouchEvent(View.java:7229)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2237)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1936)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2177)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1482)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.app.Activity.dispatchTouchEvent(Activity.java:2469)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:260)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2125)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.View.dispatchPointerEvent(View.java:7414)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3523)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3455)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4565)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4543)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4647)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.os.MessageQueue.nativePollOnce(Native Method)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.os.MessageQueue.next(MessageQueue.java:125)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.os.Looper.loop(Looper.java:124)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at android.app.ActivityThread.main(ActivityThread.java:4963)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at java.lang.reflect.Method.invokeNative(Native Method)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at java.lang.reflect.Method.invoke(Method.java:511)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
02-03 17:17:28.609: E/AndroidRuntime(3757):     at dalvik.system.NativeStart.main(Native Method)

您忘记创建 Handler 的新对象。添加

handler=new Handler(); 

AudioRecorderclass,你会没事的。

此外,我认为您在设置值时犯了另一个错误:

getCurrentPosition() 将 return 一个介于 0 和 30 之间的值。当您调用 getCurrentPosition()/1000 时,技术上它不能超过 0,因为 int1/int1+int2 将始终 return 0. Seekbar取值范围为0到100. 注释掉/1000所以是

int mCurrentPosition = mRecorder.getCurrentPosition();
                       mSeekBar.setProgress(mCurrentPosition);

你应该没事。

getCurrentPosition()*10/3 将使 Seekbar 在录音达到 30 秒标记时到达终点。