Why should I get NPE in this state?

I am trying to record audio from a device.

I created an AudioRecord object and managed it through an activity loop.

When my application switches to the background image, it stops, and in the foreground it continues.

When recording is in progress, I want to get samples from the recorder into an array of bytes

This is the code I use for this:

private void startRecorder() {
    Log.d(TAG, "before start recording");
    myBuffer = new byte[2048];
    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
    audioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_DTMF, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
    myRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 2048);

    myThread = new Thread() {
        public void run() {
            while (true) {
                if (myRecorder != null && myRecorder.getState() == AudioRecord.RECORDSTATE_RECORDING) {
                    myRecorder.read(myBuffer, 0, 2048);
                    recordingSampleNumber++;
                    if (recordingSampleNumber % 10 == 0) {
                        Log.d(TAG, "recording sample number:" + recordingSampleNumber);
                    }
                }
            }
        }
    };
    myThread.setPriority(Thread.MAX_PRIORITY);

    myRecorder.startRecording();
    myThread.start();
    Log.d(TAG, "after start recording");
}

My problem: from time to time I get the following error:

06-22 11:44:21.057: E/AndroidRuntime(17776): Process: com.example.microphonetestproject2, PID: 17776
06-22 11:44:21.057: E/AndroidRuntime(17776): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.media.AudioRecord.getState()' on a null object reference
06-22 11:44:21.057: E/AndroidRuntime(17776):    at com.example.microphonetestproject2.MicrophoneTestApp$3.run(MicrophoneTestApp.java:108)

My question is: why should I get NPE on myRecorder.getState () when only half of the line before I wrote "if myRecorder!=null"

+4
source share
1 answer

It looks like a concurrency issue.

, myRecorder!= null ​​ , , , , , , .

. , .

while (true) {
    synchronized (myRecorder) {
        if (myRecorder != null && myRecorder.getState() == AudioRecord.RECORDSTATE_RECORDING) {
            myRecorder.read(myBuffer, 0, 2048);
            recordingSampleNumber++;
            if (recordingSampleNumber % 10 == 0) {
                Log.d(TAG, "recording sample number:" + recordingSampleNumber);
            }
        }
    }
}

, , . null , interrupt join:

private Thread mRecorderThread;

private void startRecorder() {
    myRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 2048);

    mRecorderThread = new Thread() {
        public void run() {
            while (true) {
                if (!isInterrupted() && myRecorder.getState() == AudioRecord
                        .RECORDSTATE_RECORDING) {
                    myRecorder.read(myBuffer, 0, 2048);
                    recordingSampleNumber++;
                    if (recordingSampleNumber % 10 == 0) {
                        Log.d(TAG, "recording sample number:" + recordingSampleNumber);
                    }
                }
            }
        }
    };
    mRecorderThread.setPriority(Thread.MAX_PRIORITY);
    myRecorder.startRecording();
    mRecorderThread.start();
    Log.d(TAG, "after start recording");
}

private void stopRecorder() {
    mRecorderThread.interrupt();
    // Wait for the thread to finish (for the interruption to take effect)
    try {
        mRecorderThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    myRecorder.stop();
}

interrupt(), , , , , . join() Thread .

+1

All Articles