android – 为什么我会在这种状态下获得NPE
作者:互联网
我正在尝试从设备录制音频.
我创建了一个AudioRecord对象,并在活动周期中对其进行管理.
当我的应用程序转到后台时,它会停止,而当它在前台时会继续.
录音运行时,我想将录音机中的样本转换为字节数组
这是我用来做的代码:
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");
}
我的问题是:每隔一段时间我就会收到以下错误:
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)
我的问题是:为什么我在myRecorder.getState()上获得一个NPE,而在我写“if myRecorder!= null”之前只有半行
解决方法:
这看起来像一个并发问题.
似乎在检查myRecorder!= null之后,该变量实际上在另一个线程中设置为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以取消线程,使用内置中断和连接方法:
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()的帮助下,您可以在中断线程后等待线程完成.
标签:android,audiorecord 来源: https://codeday.me/bug/20190708/1400130.html