如何在Android中录制来自配对蓝牙音频设备(即Moster Clarity Bluetooth Speaker)的语音。
我已经在Android中与该设备配对,我想从设备上的麦克风录制语音(而不是使用手机的内置麦克风)。
这是我用于录制的代码:
try {
isRecording = true;
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
if (file == null) {
File rootDir = Environment.getExternalStorageDirectory();
file = File.createTempFile(PREFIX, EXTENSION, rootDir);
}
recorder.setOutputFile(file.getAbsolutePath());
recorder.prepare();
recorder.start();
timDown = new RecordCountDown(10000, 1000);
timDown.start();
} catch (Exception e) {
Log.i("Error Message", "Error Message :" + e.getMessage());
}
我该怎么做?
答案 0 :(得分:7)
尝试此代码可能对您有所帮助..
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
Log.d(TAG, "Audio SCO state: " + state);
if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
/*
* Now the connection has been established to the bluetooth device.
* Record audio or whatever (on another thread).With AudioRecord you can record with an object created like this:
* new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
* AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
*
* After finishing, don't forget to unregister this receiver and
* to stop the bluetooth connection with am.stopBluetoothSco();
*/
unregisterReceiver(this);
}
}
}, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
Log.d(TAG, "starting bluetooth");
am.startBluetoothSco();
答案 1 :(得分:2)
从蓝牙耳机录音的代码
public class Recording {
static int count = 0;
static String Shared;
static String bFlag;
public static int TIMEOUT = 5000;
public static int COUNTDOWN_INTERVAL = 1000;
static Context context;
public static void checkAndRecord(Context context,
OnBluetoothRecording BluetoothRecording, boolean resume) {
// Check bluetooth flag And Bluetooth is ON or OFF
if (getBluetoothFlag(context) && isBluetoothON()) {
// Check for bluetooth and Record
startBluetoothRecording(BluetoothRecording, resume, context);
} else {
// If Bluetooth is OFF Show Toast else Dont Show
if (getBluetoothFlag(context) && !isBluetoothON()) {
// false because recording not started
Toast.makeText(context,
"Bluetooth is OFF. Recording from Phone MIC.",
Toast.LENGTH_SHORT).show();
BluetoothRecording.onStartRecording(resume, false);
} else {
// false because recording not started
BluetoothRecording.onStartRecording(resume, false);
}
}
}
private static void startBluetoothRecording(
final OnBluetoothRecording BluetoothRecording,
final boolean resume, Context context) {
// TODO Auto-generated method stub
final int MAX_ATTEPTS_TO_CONNECT = 3;
final AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
final CountDownTimer timer = getTimer(BluetoothRecording, audioManager,
resume);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(
AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
// cancel Timer
timer.cancel();
context.unregisterReceiver(this);
// pass through and true because
// recording from bluetooth so set 8000kHz
BluetoothRecording.onStartRecording(resume, true);
} else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) {
if (count > MAX_ATTEPTS_TO_CONNECT) {
context.unregisterReceiver(this);
// Stop BluetoothSCO
audioManager.stopBluetoothSco();
// reset Counter
count = 0;
// stop timer
timer.cancel();
// false because still recording not started
BluetoothRecording.onStartRecording(resume, false);
} else {
// Increment Disconnect state Count
count++;
}
}
}
}, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
// Start the timer
timer.start();
audioManager.startBluetoothSco();
}
// set the Timeout
private static CountDownTimer getTimer(
final OnBluetoothRecording BluetoothRecording,
final AudioManager audioManager, final boolean resume) {
// TODO Auto-generated method stub
return new CountDownTimer(TIMEOUT, COUNTDOWN_INTERVAL) {
@Override
public void onTick(long millisUntilFinished) {
// Do Nothing
}
@Override
public void onFinish() {
// stopBluetoothSCO() and start Normal Recording
audioManager.stopBluetoothSco();
// false because recording button is already clicked but still
// not recording.
BluetoothRecording.onStartRecording(resume, false);
}
};
}
// Return's the bluetooth state
private static boolean isBluetoothON() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter
.getDefaultAdapter();
return bluetoothAdapter.isEnabled();
}
// Return's the bluetoothFlag state
private static boolean getBluetoothFlag(Context context) {
// shared pref
SharedPreferences sp = context.getSharedPreferences(Shared,
Context.MODE_PRIVATE);
return sp.getBoolean(bFlag, false);
}
}
接口OnBluetoothRecording.java
public interface OnBluetoothRecording {
void onStartRecording(boolean state,boolean bluetoothFlag);
void onCancelRecording();
}
答案 2 :(得分:1)
关键是致电audioManager.startBluetoothSco()。
希望在手机未通话时向/从蓝牙SCO耳机发送和接收音频的应用程序可以使用此方法。
这是一个异步操作,因此,您可以注册一个BroadcastReceiver
,一旦音频开始通过蓝牙耳机录制,就会收到通知
private BroadcastReceiver mBluetoothScoReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// Start recording audio
}
}
};
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
registerReceiver(mBluetoothScoReceiver, intentFilter);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.startBluetoothSco();
}
文档中还提到了一些非常重要的内容
应用程序可以在调用startBluetoothSco()之前通过读取接收器注册返回的意图来检查SCO音频状态。如果状态已经是CONNECTED,则在调用startBluetoothSco()之后,不会通过intent接收状态更改。
而且......
然而,调用startBluetoothSco()会使连接保持活动状态,以防当前启动器停止连接。
这意味着如果SCO连接已经处于活动状态,则不必等待接收器被调用。这是更新的代码段。
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
Intent intent = registerReceiver(mBluetoothScoReceiver, intentFilter);
if (intent == null) {
Log.e(TAG, "Failed to register bluetooth sco receiver...");
return;
}
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// Start recording
}
// Ensure the SCO audio connection stays active in case the
// current initiator stops it.
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.startBluetoothSco();
}
如果您不使用它,则应该停止SCO连接。
private void onPause() {
super.onPause();
unregisterReceiver(mBluetoothScoReceiver);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.stopBluetoothSco();
}
您还需要AndroidManifest.xml
文件
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>