I am trying to send audio file via Bluetooth using the sample BluetoothChat code.
I have created a class that converts audio into bytes and vise-versa.
Here are the modifications I have made in the sample code
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
//Convert noti.mp3 into byte array (noti.mp3 is an audio file I am using for testing)
try{send = Converter.convertAudioToBytes(path+"noti.mp3");}
catch(Exception e){Logger.append("Error while converting audio into bytes", e);}
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
I am also adding some bytes at the end of the audio to identify the endOfFile on the receiving end.
On the receiving end I have updated the mHandler
//List to store bytes received from the other device
private List<Byte> list = new ArrayList<Byte>();
case Constants.MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
//Status for end of data
boolean endOfData = false;
//Add bytes to the Array list
for(int i=0;i<msg.arg1;i++){list.add(readBuf[i]);}
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
mConversationArrayAdapter.add(mConnectedDeviceName + ": " + readMessage);
//Check if the received message contains this string
//Also check if the length of the data is less than 990
if(readMessage.contains("END OF AUDIO FILE") && msg.arg1<990){
endOfData = true;
}
//Check if all the data has been received
if(endOfData)
{
try{
Converter.convertBytesToAudio(list,path);
mConversationArrayAdapter.add(mConnectedDeviceName + ": Audio saved!");
}
catch(Exception e){
Logger.append("Error while converting bytes to audio", e);
}
finally{
list.clear();
}
}
break;
The code works fine for small audio files but when I send a file that is bigger than 3KB it does not properly receive the data and does not transfer it to audio properly.
I tried to send some long text like this
String str = "Message number ";
for(int i=0;i<1000;i++){message += str+i+" ,\n";}
byte[] send = message.getBytes();
mChatService.write(send);
on the receiving end I noticed, the messages received are not synchronized.
Can someone please help me solve this issue, or any other way to transfer audio messages via Bluetooth. I am trying to do something like WhatsApp audio messages but via Bluetooth.
Any help is appreciated.Thanks
Still waiting for an answer :( Please help
Related
Based on SDK's bluetoothchat example I'm working on an app that transmits strings between an android device and arduino.
I've the folowing issues:
1- If I use this code I loose the first byte sent by arduino:
// Keep listening to the InputStream while connected
while (true) {
try {
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes,-1, buffer).sendToTarget();
But This way it works :
bytes = mmInStream.available();
if(bytes != 0) {
SystemClock.sleep(100); //pause and wait for rest of data.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
}
Any explanation please?
2- Arduino sends the string "OK" when recieves a string from the device.
How to use this as an ACK(nowledgment) in my app ?
I tried this but with no success:
String ack = ""; //global variable
sendstring("test string");// send a test string to arduino
SystemClock.sleep(100); //wait for arduino response
if(ack.equals("OK")) txtv.setText(" well received"); //well done
in the handler:
if(msg.what == Bluetooth.MESSAGE_READ){
String receivedstring = new String((byte[]) msg.obj, 0, msg.arg1);
ack = receivedstring ;
I don't get ack = "OK" , and " well received" is not displayed in the text view !!
Many thanks for ur help
Hi i dont know that much about blutoothchat but i may have an anwser to your first question. If you dont already have an answer.
// Keep listening to the InputStream while connected
while (true) {
try {
bytes = mmInStream.read(buffer); // it may not work because its not reading from the first line unlike this: bytes = mmInStream.read(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes,-1, buffer).sendToTarget();
I am building an Android application to communicate with my NR-42 bluetooth device. I am able to connect to the bluetooth and send data to the device which is a PIC18F but I am not able to receive bluetooth data from my device to my android phone.
I am following this example http://solderer.tv/data-transfer-between-android-and-arduino-via-bluetooth/comment-page-1/
When I use tera-term it shows me that the bluetooth module is doing what it is suppose to do, but I can't get the data in my textViews. I am trying to send float data. I am new to android but the issue is happening here I assume.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
btnOff.setEnabled(true);
btnOn.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
"
The input stream is being read here."
public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
Log.d(TAG, "sent handler");
} catch (IOException e) {
break;
}
}
}
Has anyone come across this issue or can help me out?
Thanks
I use some of the Bluetooth chat samplecode for sending a SMALL (177 byte to 3617 byte) "settings-file" "securly" between apps.
when it is under 1024 bit everything works fine: (so the 177 works PERFECT)
sendingdevice press "send button" and the reciver gets it (with a dialog if they want it..) (and I save the "string" to a "settings"file on that device)
but if the file is over 1024 it gets chunkt/cut off.. (example: 2000byte)
so the file gets corrupted (data-loss but some info remains..)
Probably I need to "split" my file in 1024 bits and send the bits and in the receiver-end, I need to "add them all up"..
but I don't know the "standard best practices" for this, do you have any suggestions?
I have tryed to "only higher" the 1024 byte to 65536byte, but that don't work..
(or maby I do this wrong..)
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;
}
}
}
sedan write:
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mmOutStream.flush();
// 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);
}
}
and when i "click on send settings":
String message = view.getText().toString();
String settingInAString = getSettingInALargeString();
sendMessage(settingInAString);
and in "sendMessage":
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send); //SO convert to byte and then send the byte..
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
and:
/**
* Write to the ConnectedThread in an unsynchronized manner
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
but I think you know what Im lookning for ...
(or can I some how change the "BluetoothChat" so it can sent and recive a large Sring, and not "byte:s"? :-) )
Best REGARDS to you all :-)
EDIT:
on the reader side I have this:
on the "reader end" I have:
....
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
//only a byte redebuffer, hmm can I change this? or do i use a whileloop?
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
recivedStringCheckFirst(readMessage);
//simple-check if the data is a "data-setting-file"
String [] allSettingsInALargeArray1 = doSplitOnLargeString(readMessage);
int titleArrayLength1 = getLengthOffTheUpCommingTitleArrayFromNew(allSettingsInALargeArray1); //this do a split and looks if it is 1,2,3..20 settings..)
mConversationArrayAdapter.add(titleArrayLength1 + " datasettings recived from " + mConnectedDeviceName + " SAVE THIS?");
//this type this text to the "chatwindow"
break;
Here is the splitting-chunk-problem now..
if i send under ~ 1024 I receive the correct amount of settings ant i can save this fine :-)
If i sent larger then 1024 I get first for exampel "6 settings from.." and then a new message that I recived "1 settings from.." message :-(
just for your info:
protected void recivedStringCheckFirst(String readMessage) {
String eventuellSettings = readMessage;
if (isThisASettingFile(eventuellSettings)){
//of ok..
System.out.println("incommingISAsetting :-) ");
inkommenSettings = eventuellSettings;
showDialog(); //dialog for save settings?
}
if (!isThisASettingFile(eventuellSettings)){
//not a settingsfile!
Toast.makeText(this, "try again..", Toast.LENGTH_LONG).show();
}
}
so i think it is:
case MESSAGE_READ:
is not only called if a complete file is received,
it is also called if a small chunks is received.
So I probably should place the "readFile-chunk" in a separate buffer
(i.e. mNewBufForFile += readFileChunk)
And then check the mNewBufForFile has a complete packet in it (how?). If it is done: I "save" the file message and then clear all buffer.
but how can i "split this from "Message_read", and do I "add a stopping bit" so i can check when i recive all the data? or can i do this better?
You can send as many bytes as you want. They come in in chunks smaller than the size of buffer (1024). Indeed the original code will mix all up caused by using one buffer. Change
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();
to
while (true) {
try {
byte[] buffer = new byte[1024];
// Read from the InputStream
int nbytes = mmInStream.read(buffer);
Log.i(TAG, "read nbytes: " + nbytes);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, nbytes, -1, buffer)
.sendToTarget();
The data still comes in in chuncks but now you get all displayed in the rigth sequence.
As the chunck sizes -during some tests- are smaller than 1024 it makes no sense to have a bigger buffer. If you want to transfer a real file you should concatenate all together. This is a normal action using sockets.
Got a problem at receiving bytes from bluetooth socket. I'm trying to send message created by arduino - couple of single bytes values i.e. 0x41, 0x05, 0xFF(...) into my phone with android. It works fine until one of these value is zero (0x00). Transmission hangs until new message comes. Anyone meet with that situation?
My "reader" works in separate thread, processBuffer() do sth with data that should be received:
public void run() {
while(stop == false){
try {
bytes = InStream.read(readbuffer);
for (int i = 0; i < bytes; i++){
Log.d("FRAME", "Read bytes "+readbuffer[i]);
}
Log.d("FRAME", "Read number of bytes "+bytes);
processBuffer(bytes);
} catch (Exception e){
Log.d("BT_debug", "Cannot read bytes");
Log.d("BT_debug", "iterator: "+iterator);
e.printStackTrace();
break;
}
}
}
I'm really stumped with this and I've trying to debug for the passed three days. Hopefully someone will be able to tell me what I am doing wrong.
I am implementing a BlockingQueue (FIFO) buffer to receive information being streamed from my PC over bluetooth. I am sending prerecorded electrocardiogram signal over a Hyperterminal link using RealTerm.
I have tested the buffer as I start up the app by adding values and then removing them, and it seems to work as it should.
The problem comes in when I try to store in the buffer while I'm receiving data from the bluetooth connection. I don't know if I am adding faster than the BlockingQueue can cope, but when I stop the data transmission and check my buffer, the whole buffer contains the last value that was added. The size of the buffer is correct, but the content isn't.
Here is my buffer:
public class IncomingBuffer {
private static final String TAG = "IncomingBuffer";
private BlockingQueue<byte[]> inBuffer;
public IncomingBuffer() {
inBuffer = new LinkedBlockingQueue<byte[]>();
Log.i(TAG, "Initialized");
}
public int getSize() {
int size;
size = inBuffer.size();
return size;
}
// Inserts the specified element into this queue, if possible. Returns True
// if successful.
public boolean insert(byte[] element) {
Log.i(TAG, "Inserting " + element[0]);
boolean success = inBuffer.offer(element);
return success;
}
// Retrieves and removes the head of this queue, or null if this queue is
// empty.
public byte[] retrieve() {
Log.i(TAG, "Retrieving");
return inBuffer.remove();
}
// Retrieves, but does not remove, the head of this queue, returning null if
// this queue is empty.
public byte[] peek() {
Log.i(TAG, "Peeking");
return inBuffer.peek();
}
}
The portion of my BluetoothCommunication class which receives the information and sends it to the buffer is the following:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
ringBuffer = new IncomingBuffer();
byte[] buffer = new byte[1024];
Log.i(TAG, "Declared buffer byte");
int bytes;
byte[] retrieve;
int size;
Log.i(TAG, "Declared int bytes");
//Setting up desired data format 8
write(helloworld);
Log.i(TAG, "Call write(initialize)");
// Keep listening to the InputStream while connected
while (true) {
try {
Log.i(TAG, "Trying to get message");
// Read from the InputStream
bytes = mmInStream.read(buffer);
//THIS IS WHERE THE BYTE ARRAY IS ADDED TO THE IncomingBuffer
RingBuffer.insert(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
Log.i(TAG, "Sent to target" +ringBuffer.getSize());
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothCommService.this.start();
break;
}
}
}
So an example of my problem would be:
Send values over bluetooth connection (8 bit values from 1 to 20). In the insert method of the IncomingBuffer class, the log message confirms the proper value is sent. When values are retrieved from buffer, it contains twenty byte arrays which all contain the last number inserted (20).
Any clue as to why the buffer would work in other circumstances but not during the bluetooth communication?
I figured out what my problem was.
When I was using the variable buffer to read from mmInStream and then pass that to the ringBuffer, I pass the same byte array variable every time i go through the while loop. From what I can understand that simply assigns a specific memory location where the byte array is calculated and that is why at the end all of the elements in my ringBuffer are the last value that was assigned to 'buffer' from the mmInStream.
What i did to change that is make a separate variable that i clone the 'buffer' byte array to. Before I pass 'buffer' to 'RingBuffer', i do the following:
byte[] newBuf;
newBuf = buffer.clone();
ringBuffer.store(newBuf);
This takes care of my problem.