Я пытаюсь создать приложение для рации с Bluetooth для одного из моих классов, но не могу заставить его работать правильно. Я изменил пример BluetoothChat (http://developer.android.com/guide/topics/connectivity/bluetooth.html), чтобы попытаться удовлетворить мои потребности, и я могу успешно передавать голосовые записи с одного телефона на другой, но получается очень статично. Я использую AudioRecord и AudioTrack для записи и воспроизведения.
У меня есть эти глобальные переменные
private static final int RECORDER_SAMPLERATE = 8000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private AudioTrack audioTrack = null;
private int bufferSize = 0;
private Thread recordingThread = null;
private boolean isRecording = false;
и в моем методе onCreate я устанавливаю bufferSize и инициализирую AudioTrack.
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_STEREO,
RECORDER_AUDIO_ENCODING, bufferSize, AudioTrack.MODE_STREAM);
Вот мой код, когда нажата кнопка записи / отправки (в настоящее время у меня есть только для записи 3 секунд данных).
private void startRecording() {
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);
int i = recorder.getState();
if (i == 1)
recorder.startRecording();
isRecording = true;
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run()
{
enableButtons(false);
if(null != recorder){
isRecording = false;
recorder.stop();
recorder.release();
recorder = null;
recordingThread = null;
}
}
});
}
}, 3000);
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
writeOutAudioData();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
private void writeOutAudioData() {
byte data[] = new byte[bufferSize];
int read = 0;
while (isRecording)
{
read = recorder.read(data, 0, bufferSize);
if (AudioRecord.ERROR_INVALID_OPERATION != read)
{
mChatService.write(data);
//TODO
}
}
}
Вот код, который обрабатывает все входящие и исходящие передачи
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
/**
* Write to the connected OutStream.
* @param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
вот код моего обработчика, который получает информацию от BluetoothChatService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (D)
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
setStatus(getString(R.string.title_connected_to,
mConnectedDeviceName));
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
setStatus(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
//byte[] writeBuf = (byte[]) msg.obj;
break;
case MESSAGE_READ:
final byte[] readBuf = (byte[]) msg.obj;
final byte bytes = (byte) msg.arg1;
Thread audioPlay = new Thread()
{
public void run(){
audioTrack.play();
audioTrack.write(readBuf, 0, readBuf.length);
audioTrack.stop();
}
};
audioPlay.start();
break;
}
}
};
Я просто не понимаю, какой размер буфера byte [] должен быть в классе ConnectedThread. Стоит ли оставить 1024 или поменять на что-нибудь другое? И я не могу понять, как правильно читать эти входящие байты и записывать их в AudioTrack для воспроизведения (без статики). Я использую Android 4.3 на одном телефоне и 4.2.2 на другом. Любая помощь будет принята с благодарностью! Спасибо!