启用麦克风后,一台设备无法通过耳机播放音频通话
One device doesn't play audio call through earpiece after enabling microphone
我正在编写 Messenger(具有 VoIP 功能),用户可以在其中分别打开 off/on 扬声器和微型 phone。我刚刚添加了一个功能,用户可以将 phone 带到他的耳朵,然后屏幕关闭,他可以通过耳机听到对话。这就是问题所在。在一台设备(带有自定义固件)上,当我同时打开扬声器和微型 phone 并将 phone 放在耳边时,我听不到任何声音。
我的部分代码:
打开扬声器:
private void headsetStart()
{
if (mPlayMessages == null)
{
mHeadsetButton.setBackgroundResource(R.drawable.headset_on);
audioManager.setMode(audioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(!nearProximity);
// turn off screen on near proximity sensor
mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, ":headsetStart");
mWakeLock.acquire();
mBeOnAirThread = new BeOnAirThread();
mBeOnAirThread.start();
if (partnerOnAir && !mIsStarted)
{
micStart();
}
}
}
private class BeOnAirThread extends Thread {
// Sample rate must be one supported by Opus.
static final int SAMPLE_RATE = 16000;
// Number of samples per frame is not arbitrary,
// it must match one of the predefined values, specified in the standard.
static final int FRAME_SIZE = 160;
// 1 or 2
static final int NUM_CHANNELS = 1;
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
// init audio track
AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
minBufSize,
AudioTrack.MODE_STREAM);
.....................................
正在初始化微phone:
private class RecordThread extends Thread {
// Sample rate must be one supported by Opus.
static final int SAMPLE_RATE = 16000;
// Number of samples per frame is not arbitrary,
// it must match one of the predefined values, specified in the standard.
static final int FRAME_SIZE = 160;
// 1 or 2
static final int NUM_CHANNELS = 1;
byte[] textBuf;
int iav;
int off;
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
// initialize audio recorder
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
minBufSize);
..........................................
根据经验确定,如果在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前停止 RecordThread 并在它之后重新启动它,则耳机可以正常工作。
但是为我重新连接到服务器是不可取的。所以我也尝试在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前做 "recorder.stop(); recorder.release()" 并在它之后重建新的 AudioRecord,但它没有帮助。
有什么想法吗?
终于可以用了。
实验表明我确实不需要release和reconstruct AudioRecord
我所需要的只是 "audioManager.setSpeakerphoneOn(!nearProximity);" 和 "recorder.startRecording();"
之间的一些延迟(~1 秒)
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
boolean oldNear = nearProximity;
if (event.values[0] >= -SENSOR_SENSITIVITY && event.values[0] <= SENSOR_SENSITIVITY) {
nearProximity = true;
} else {
nearProximity = false;
}
if (mBeOnAirThread != null && oldNear != nearProximity)
{
if (nearProximity && mIsStarted)
nearChanged = true;
else
audioManager.setSpeakerphoneOn(!nearProximity);
}
}
}
在记录循环中:
if (nearChanged)
{
recorder.stop();
audioManager.setSpeakerphoneOn(!nearProximity);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
recorder.startRecording();
nearChanged = false;
}
我正在编写 Messenger(具有 VoIP 功能),用户可以在其中分别打开 off/on 扬声器和微型 phone。我刚刚添加了一个功能,用户可以将 phone 带到他的耳朵,然后屏幕关闭,他可以通过耳机听到对话。这就是问题所在。在一台设备(带有自定义固件)上,当我同时打开扬声器和微型 phone 并将 phone 放在耳边时,我听不到任何声音。
我的部分代码:
打开扬声器:
private void headsetStart()
{
if (mPlayMessages == null)
{
mHeadsetButton.setBackgroundResource(R.drawable.headset_on);
audioManager.setMode(audioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(!nearProximity);
// turn off screen on near proximity sensor
mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, ":headsetStart");
mWakeLock.acquire();
mBeOnAirThread = new BeOnAirThread();
mBeOnAirThread.start();
if (partnerOnAir && !mIsStarted)
{
micStart();
}
}
}
private class BeOnAirThread extends Thread {
// Sample rate must be one supported by Opus.
static final int SAMPLE_RATE = 16000;
// Number of samples per frame is not arbitrary,
// it must match one of the predefined values, specified in the standard.
static final int FRAME_SIZE = 160;
// 1 or 2
static final int NUM_CHANNELS = 1;
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
// init audio track
AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
minBufSize,
AudioTrack.MODE_STREAM);
.....................................
正在初始化微phone:
private class RecordThread extends Thread {
// Sample rate must be one supported by Opus.
static final int SAMPLE_RATE = 16000;
// Number of samples per frame is not arbitrary,
// it must match one of the predefined values, specified in the standard.
static final int FRAME_SIZE = 160;
// 1 or 2
static final int NUM_CHANNELS = 1;
byte[] textBuf;
int iav;
int off;
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
// initialize audio recorder
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
SAMPLE_RATE,
NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
minBufSize);
..........................................
根据经验确定,如果在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前停止 RecordThread 并在它之后重新启动它,则耳机可以正常工作。 但是为我重新连接到服务器是不可取的。所以我也尝试在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前做 "recorder.stop(); recorder.release()" 并在它之后重建新的 AudioRecord,但它没有帮助。
有什么想法吗?
终于可以用了。
实验表明我确实不需要release和reconstruct AudioRecord
我所需要的只是 "audioManager.setSpeakerphoneOn(!nearProximity);" 和 "recorder.startRecording();"
之间的一些延迟(~1 秒)@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
boolean oldNear = nearProximity;
if (event.values[0] >= -SENSOR_SENSITIVITY && event.values[0] <= SENSOR_SENSITIVITY) {
nearProximity = true;
} else {
nearProximity = false;
}
if (mBeOnAirThread != null && oldNear != nearProximity)
{
if (nearProximity && mIsStarted)
nearChanged = true;
else
audioManager.setSpeakerphoneOn(!nearProximity);
}
}
}
在记录循环中:
if (nearChanged)
{
recorder.stop();
audioManager.setSpeakerphoneOn(!nearProximity);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
recorder.startRecording();
nearChanged = false;
}