java 调用 startRecording() 方法时 Android AudioRecord 失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34860767/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android AudioRecord failing when calling the startRecording() method
提问by Timor Gruber
I'm trying to record audio in android and store it in an array of bytes, and for that I use Android's AudioRecord built-in class.
I've already used this class before, and all was good, but for some reason, it seems the AudioRecord won't work anymore.
我正在尝试在 android 中录制音频并将其存储在一个字节数组中,为此我使用了 Android 的 AudioRecord 内置类。
我以前已经使用过这个类,一切都很好,但是由于某种原因,AudioRecord 似乎不再起作用了。
The problem is that the AudioRecord gets initialized and shows no errors, but when it's time to actually record something, by calling its' startRecording() method, something is failing and I don't even get a proper reason why.
问题是 AudioRecord 被初始化并且没有显示任何错误,但是当需要实际记录某些东西时,通过调用它的 startRecording() 方法,某些东西失败了,我什至没有得到正确的原因。
This is ALLthe output from Logcat after calling this method:
这是调用此方法后 Logcat 的所有输出:
01-18 18:54:49.545 11303-11338/com.mypackage E/android.media.AudioRecord﹕ MediaRecorder prepare CallingPid = 11303 Callinguid= 10128
01-18 18:54:49.545 11303-11338/com.mypackage E/android.media.AudioRecord﹕ java.lang.Throwable
at android.media.AudioRecord.startRecording(AudioRecord.java:631)
at mypackage.AudioRecorder.record(AudioRecorder.java:179)
Of course no audio gets recorded after that, for those wondering if it's just an internal error message.
当然,在那之后不会记录任何音频,对于那些想知道这是否只是内部错误消息的人来说。
This is the code for initializing the AudioRecord class:
这是初始化 AudioRecord 类的代码:
int bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, RECORDER_CHANNEL, RECORDER_AUDIO_ENCODING);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE && bufferSize > 0)
{
// check if we can instantiate and have a success
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, AUDIO_SAMPLE_RATE, RECORDER_CHANNEL,
RECORDER_AUDIO_ENCODING, bufferSize);
if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
{
m_Recorder = recorder;
m_RecordingThread = Executors.newSingleThreadExecutor();
m_IsInitialized = true;
return;
}
}
When the constants that are used are:
当使用的常量是:
/**
* Recorded audio's sample rate.
*/
private static final int AUDIO_SAMPLE_RATE = 44100;
/**
* Recorded audio's channel.
*/
private static final int RECORDER_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
/**
* Recorded audio's encoding.
*/
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
The error is happening here:
错误发生在这里:
if (m_Recorder != null)
m_Recorder.startRecording();
So after seeing this happen a couple of times, I decided to go deeper and try to debug it, going as deep as I can, to the source of error in the AudioRecord class itself, using Jetbrain's decompiler.
For some strange reason, as soon as the app hit the breakpoint located at the source of error, the next step-over couldn't be completed, as the AudioRecord has crashed yet again, with the same error message.
所以在看到这种情况发生了几次之后,我决定更深入地尝试调试它,尽可能深入地使用 Jetbrain 的反编译器调试 AudioRecord 类本身的错误源。
出于某种奇怪的原因,一旦应用程序击中位于错误源的断点,下一步就无法完成,因为 AudioRecord 再次崩溃,并显示相同的错误消息。
The next step for me was creating a sample project just to test AudioRecord's functionality, but this time I added an AudioTrack as well, that will output all my recordings instantly (a kind of a loopback), in case the AudioRecord class manages to record something, with or without the error.
And so the magic has happened - The app is working, AudioRecord is recording, and AudioTrack is playing.
It seemed really strange that the AudioTrack class suddenly resolved all my issues, so I removed it from my code and tried running the app yet again.
This time, the AudioRecord worked without all problems, and even though I couldn't hear its' output, I can assure you it has been recording.
我的下一步是创建一个示例项目只是为了测试 AudioRecord 的功能,但这次我也添加了一个 AudioTrack,它将立即输出我的所有录音(一种回送),以防 AudioRecord 类设法录制某些内容, 有或没有错误。
所以神奇的事情发生了 - 应用程序正在运行,AudioRecord 正在录音,AudioTrack 正在播放。
AudioTrack 类突然解决了我的所有问题,这看起来真的很奇怪,所以我从我的代码中删除了它并再次尝试运行该应用程序。
这一次,AudioRecord 工作没有任何问题,即使我听不到它的输出,我可以向你保证它一直在录音。
With a bit of relief, I thought to my myself that I've finally overcame this issue, and I'm ready to move forward, so I added some extra code to encode and decode the recorded audio data.
To hear an output, I returned the code using the AudioTrack class, and ran the app.
稍稍松了口气,我心里想我终于克服了这个问题,我准备继续前进,所以我添加了一些额外的代码来对录制的音频数据进行编码和解码。
为了听到输出,我使用 AudioTrack 类返回了代码,然后运行了应用程序。
Wanna hear a funny thing? The app has crashed with the same error, AGAIN.
想听有趣的事情吗?该应用程序因相同的错误再次崩溃。
Now theoretically the problem could be not releasing the AudioRecord instance when done using it, but I've covered that too from the very beginning.
现在理论上问题可能不是在使用完 AudioRecord 实例后释放它,但我从一开始就已经涵盖了这一点。
I've tried looking practically everywhere on the internet for a solution, but it seems as if no one has even encountered a problem like this before.
我已经尝试在互联网上几乎到处寻找解决方案,但似乎以前没有人遇到过这样的问题。
Also, I'd like to point out that I've tried resetting my device, the ADB plugin, and rebuilding all projects.
另外,我想指出我已经尝试重置我的设备、ADB 插件并重建所有项目。
I'm using a Meizu MX5 phone, with Android Lollipop(API 21).
我正在使用带有 Android Lollipop(API 21)的魅族 MX5 手机。
采纳答案by Timor Gruber
Well, I solved the problem, or at least a part of it, causing it to work now.
The thing is I tried to read more bytes than the size of my pre-allocated buffer, upon calling the read() method of the AudioRecord class.
Although it didn't solve the main issue of this post, which is the strange error message and the uncaught exception, it made the AudioRecord work perfectly, so for me this thread can be seen as answered and closed!
好吧,我解决了这个问题,或者至少解决了它的一部分,使其现在可以工作。问题是在调用 AudioRecord 类的 read() 方法时,我试图读取比预分配缓冲区大小更多的字节。
虽然它没有解决这个帖子的主要问题,即奇怪的错误信息和未捕获的异常,但它使 AudioRecord 完美地工作,所以对我来说,这个线程可以被视为已回答和关闭!
回答by Роман Зыков
Full code
完整代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
//import com.rdt.facerecord.R;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class StreamD extends Activity {
private Button startButton,stopButton;
public byte[] buffer;
public static DatagramSocket socket;
private int port=8089;
AudioRecord recorder;
private int sampleRate = 16000 ; // 44100 for music
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
private boolean status = true;
TextView prompt;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stream);
prompt = (TextView)findViewById(R.id.textView1);
startButton = (Button) findViewById (R.id.start_bbb);
stopButton = (Button) findViewById (R.id.stop_bbb);
startButton.setOnClickListener (startListener);
stopButton.setOnClickListener (stopListener);
}
private final OnClickListener stopListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = false;
recorder.release();
System.out.println("Recorder released");
}
};
private final OnClickListener startListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = true;
startStreaming();
}
};
public void startStreaming() {
Thread streamThread = new Thread(new Runnable() {
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
System.out.println("Socket Created");
byte[] buffer = new byte[minBufSize];
System.out.println("Buffer created of size " + minBufSize);
DatagramPacket packet;
final InetAddress destination = InetAddress.getByName("218.000.000.000");
System.out.println("Address retrieved");
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,m inBufSize*10);
System.out.println("Recorder initialized");
recorder.startRecording();
while(status == true) {
//reading data from MIC into buffer
minBufSize = recorder.read(buffer, 0, buffer.length);
//putting buffer in the packet
packet = new DatagramPacket (buffer,buffer.length,destination,port);
socket.send(packet);
System.out.println("MinBufferSize: " +minBufSize);
}
} catch(UnknownHostException e) {
System.out.println("UnknownHostException");
} catch (IOException e) {
e.printStackTrace();
System.out.println("IOException");
}
}
});
streamThread.start();
}
}
and add permission
并添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />