Android AudioRecord – 第二次不会初始化

Hej,我目前正试图让AudioRecord工作。 因为我需要一个更大的项目。 但它似乎搞得很多。 我一直在尝试很多东西,所以当我追踪这个bug时我又回到了基础。 我正在使用我的三星Galaxy S作为我的调试设备。

我的问题是,第一次重启我的设备后,我可以初始化我创建的AudioRecord对象没有问题。 但是第二次运行它时,它不会初始化AudioRecord对象。 我试过几个频率,fyi。

这是我的代码:

package android.audiorecordtest; import android.app.Activity; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class AudioRecordTest extends Activity { int frequency; AudioRecord audRec; TextView txtVw; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtVw = (TextView) findViewById(R.id.txtVw); frequency=8000; int bufferSize=(AudioRecord.getMinBufferSize(frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT))*2; if (bufferSize>0) { audRec = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); int status = audRec.getState(); if (status == AudioRecord.STATE_INITIALIZED) { txtVw.setText("Initialized" + frequency); } else { txtVw.setText("Not Initialized i=" + frequency); } } 

经过几个小时的浏览logcat信息后,我发现了这个事件

  02-28 10:46:37.048: DEBUG/dalvikvm(4477): GC_EXPLICIT freed 1801 objects / 98944 bytes in 97ms 02-28 10:46:37.048: VERBOSE/AudioRecord(4477): stop 

这似乎“释放了对AudioRecord的本机保留。所以我尝试用我的Audiorecord object.release()完成覆盖最终化。虽然没有工作但任何人有任何想法?

我能够重现你的问题(在三星手机上)。 我添加了一个释放记录的onDestroy()方法:

 @Override public void onDestroy() { super.onDestroy(); System.out.println("OnDestroy"); audRec.release(); } 

添加此项后,每次启动活动时,audioRecord似乎都会正确初始化。

我有同样的问题,通常audRec.release()确实有帮助,但如果你需要停止并启动几次,下面的代码更健壮。 另外,我遇​​到了一个问题,即录制发生在一个单独的线程中,Android有时会在运行很长时间后杀死线程。 所以看一下这段代码,它确保即使在另一个线程已经死亡时也能保持记录,并且在下面的audRec.start()中它停止并释放:

 import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; public class RecorderSingleton { private static final int FREQUENCY = 16000; public static RecorderSingleton instance = new RecorderSingleton(); private AudioRecord recordInstance = null; private int bufferSize; private RecorderSingleton() { bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); } public boolean init() { recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); if (recordInstance.getState() == AudioRecord.STATE_UNINITIALIZED) { return false; } return true; } public int getBufferSize() { return bufferSize; } public boolean start() { if (recordInstance != null && recordInstance.getState() != AudioRecord.STATE_UNINITIALIZED) { if (recordInstance.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) { recordInstance.stop(); } recordInstance.release(); } if (!init()) { return false; } recordInstance.startRecording(); return true; } public int read(short[] tempBuffer) { if (recordInstance == null) { return AudioRecord.ERROR_INVALID_OPERATION; } int ret = recordInstance.read(tempBuffer, 0, bufferSize); return ret; } public void stop() { if (recordInstance == null) { return; } recordInstance.stop(); recordInstance.release(); } } 

然后,如果您有一个记录器线程,您可以按如下方式使用它:

 import android.media.AudioRecord; public class Recorder implements Runnable { private int requiredSamples; private int takenSamples = 0; private boolean cancelled = false; public void run() { // We're important... android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); int bufferRead = 0; int bufferSize = RecorderSingleton.instance.getBufferSize(); short[] tempBuffer = new short[bufferSize]; if (!RecorderSingleton.instance.start()) { return; } try { Log.d(RoomieConstants.LOG_TAG, "Recorder Started"); while (takenSamples < requiredSamples && !cancelled) { bufferRead = RecorderSingleton.instance.read(tempBuffer); if (bufferRead == AudioRecord.ERROR_INVALID_OPERATION) { throw new IllegalStateException("read() returned AudioRecord.ERROR_INVALID_OPERATION"); } else if (bufferRead == AudioRecord.ERROR_BAD_VALUE) { throw new IllegalStateException("read() returned AudioRecord.ERROR_BAD_VALUE"); } takenSamples += bufferRead; // do something with the samples ... // ... // ... } } finally { // Close resources... stop(); } } public void stop() { RecorderSingleton.instance.stop(); } public void cancel() { cancelled = true; } } 

回答我自己的问题,我发现它可以使用AudioRecord的唯一方法是永远不要把它作为一个全局variables,不知道为什么,但它似乎不会让你正确释放实例的资源,如果你这样做所以。

您应该尝试调用audRec.stop()来释放资源。