Android time to byte array - java

I am trying to get the current time and date in an Android application and transmit it via Bluetooth. I have tried using both Time and Calendar to get the hour, minute, second, month, day, and year minus 2000. I then tried to cast each value to a byte and placed them into a byte array. However, when I try to send the values over Bluetooth they come out wrong on the other side. The format that I'm shooting for is a header (0xFF) followed by hour, minute, second, month, day, year.
public class Bluetooth extends Activity{
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private String bt_address;//00:18:E4:OC:67:FF
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth);
Button connect = (Button)findViewById(R.id.Btn_Connect);
try{
/*code removed, reads bt_address from a file or creates a file if no file exists yet*/
} catch(IOException ioe){
ioe.getStackTrace();
}
connect.setOnClickListener(new OnClickListener(){
public void onClick(View v){
try{
/*code removed, saves bt_address to a file*/
}
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
/*code removed, prompts user to turn on Bluetooth if not already on*/
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(bt_address);
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {}
mBluetoothAdapter.cancelDiscovery();
try {
btSocket.connect();
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {}
}
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {}
try {
inStream = btSocket.getInputStream();
} catch (IOException e) {}
Time time = new Time();
byte[] msgbuf = new byte[7];
msgbuf[0] = (byte)0xFF;
msgbuf[1] = (byte)time.hour;
msgbuf[2] = (byte)time.minute;
msgbuf[3] = (byte)time.second;
msgbuf[4] = (byte)(time.month + 1);
msgbuf[5] = (byte)time.monthDay;
msgbuf[6] = (byte)(time.year - 2000);
outStream.write(msgbuf);
}
)};
This code is set up to connect to a device using its Bluetooth address and send it the time stamp when a button is clicked. It will connect to the device and send a long string of numbers in the process, but I'm beginning to think that it disconnects before it sends the time stamp.

You send just one byte. Method outStream.write(int) needs int as parameter (only 8 bytes are important). So you send correctly. Have you flush messages?
It is important how you receive this message? You should read InputStream.read() method and cast integer to byte.
Maybe better solution is send bytes as outStream.write(msgbuf) and read as inputStream.read(receiveBuffer);

The Android Time class has built-in functions to convert a Time object into two different standardized string formats: format2445() and format3339(). They are already there for you, implement open standards, and somebody else has done the QA.
The strings are going to be slightly longer than the format you are working with, but at this size I doubt it will matter. Likewise, they will be only slightly more difficult for you to decode on the receiving side. Balancing that, since it's a human-readable string, it will be easier for you to debug.
I suggest you use one of these two string formats.

Related

Android: BluetoothSocket receives its own output

I have an app that connects to a RaspberryPi via Bluetooth and loops the same data to it while it receives some data back.
I had some issues with the connection so this workaround is needed to connect my android phone to the RaspberryPi: IOException: read failed, socket might be closed - Bluetooth on Android 4.3
For some reason, the android phone is receiving its own output.
The String "Hello Raspberry. It's me, AndroidPhone" is sent to the output in a never-ending loop. The incoming data (from the RaspberryPi) is also read in a never-ending loop.
But somehow I don't only receive the data from the RaspberryPi but also the string sends via smartphone. This is my code:
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter bluetoothAdapter;
UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
#Override
protected void onCreate(Bundle savedInstanceState) {
// (...)
// Only GUI-stuff until this point
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice raspberryPi = bluetoothAdapter.getRemoteDevice("B8:27:EB:56:DC:B2");
BluetoothSocket btSocket;
try {
btSocket = raspberryPi.createRfcommSocketToServiceRecord(SERIAL_UUID);
btSocket.connect();
} catch (IOException e) {
Log.e("BTError", e.getMessage());
// Workaround, found on: https://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3
try {
Log.e("BTError", "Trying fallback...");
btSocket = (BluetoothSocket) raspberryPi.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(raspberryPi, 1);
btSocket.connect();
(new Thread(new SendingThread(btSocket))).start();
(new Thread(new ReceivingThread(btSocket))).start();
} catch (Exception e2) {
Log.e("BTError", e2.getMessage());
Log.e("BTError", "Couldn't establish Bluetooth connection!");
}
}
}
private class SendingThread extends Thread {
private OutputStream out;
public SendingThread(BluetoothSocket btSocket) {
try {
out = btSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
int delay = 100000000;
while (true) {
if (delay == 0) {
Log.i("WRT", "Written to RaspberryPi");
out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
delay = 100000000;
}
delay--;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ReceivingThread extends Thread {
private InputStream in;
public ReceivingThread(BluetoothSocket btSocket) {
try {
in = btSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
int data = 0;
while (true) {
try {
data = in.read();
} catch (IOException e) {
e.printStackTrace();
}
Log.i("RCV", String.valueOf((char) data));
}
}
}
On the RaspberryPi end, everything looks normal. A simple java program starts the Linux command rfcomm listen /dev/rfcomm0 and reads from/writes to the file /dev/rfcomm0 with FileReader and FileWriter. The only relevant lines on this end are:
run {
// Inside writer-thread
bluetoothWriter = new BufferedWriter(new FileWriter("/dev/rfcomm0"));
while(true) {
bluetoothWriter.write("This is RaspPi");
bluetoothWriter.flush();
}
}
and
run {
// Inside reader-thread
bluetoothReader = new BufferedReader(new FileReader("/dev/rfcomm0"));
while(true) {
int incData = bluetoothReader.read();
System.out.print((char) incData);
}
}
Thank you for your help!
edit: Still no solution to this problem. I suspected that the RaspberryPi is somehow sending back what it received. But when I disabled that it sends out anything, the smartphone still directly receives what it has sent out.
I scoured over the Bluetooth classes sources. The workaround seems legit from the first glances. Try this first:
if (delay == 0) {
Log.i("WRT", "Written to RaspberryPi");
out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
out.flush(); // <-- You are not flushing
delay = 100000000;
}
And the message sticks in you socket for you to read over and over again.
If that does not fix it the other option I can think of is that somehow the socket is initialized to be a socket to your Android device. The .createRfcommSocket() method seems to create a socket to your own device if the Bluetooth device is null when the socket was being created. I'm not sure how this would exactly happen, but if the Raspberry Pi's state is somehow mangled after exception I suppose it could be something to look into.
On the raspy side: If you are just starting both of those threads doesn't it mean that you are constantly sending messages to /dev/rfcomm0 and flushing. I recommend that you change it so that raspy reacts to a received message by sending back the wanted message instead of spamming all the time. I'm not sure if this is part of your problem but it would at least make debugging & development a bit easier.
I am not sure if this is the solution you need, because I don't know if you are using bluetooth classic or bluetooth 4.0>+, but I wrote a library for text based BLE and WiFi P2P 2-way communication for android (and I know the Raspberry Pi is capable of BLE communication), I don't create a socket connection for BLE communication though, but I do for WiFi P2P. Take a look, I hope it helps. It isn't published yet, so you would have to clone/fork the repo.
I think you have trouble writing
As far as I know, for buffer, should use \n and ...
bluetoothWriter.write("This is RaspPi\n");
But I prefer to use a combination of DataOutputStream and BufferedReader
For Read:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line = bufferedReader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
for write:
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
String s = "Hi\n";
try {
dataOutputStream.write(s.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
It is better to correct the point made by a dear friend about flush() ...
I'm not sure, please test yourself ...

Receive Live Audio Data Via Socket on Android

I have coded an app to connect to a network socket on an Rpi over WiFi and have successfully sent data, such as a string, to and from the client and server. The next step is to have the client, my phone in this case, receive and play audio data in real time that is being sent from the server.
So far I have socket and audio variables declared. Once a button is hit, an async task "Listen" is started. I know it can connect to the socket. After that, I'm trying to open an input stream and feed it into a buffer, and then have that buffer played in real time.
I think I'm close to figuring it out, but I don't think I have it quite right yet. I have marked areas I am unsure of with TODO in my code.
public class MainActivity extends AppCompatActivity {
//audio variables
static final int sampleFreq = 44100;
static final int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
static final int streamType = STREAM_MUSIC;
static final int audioMode = MODE_STREAM;
static final int bufferSize = getMinBufferSize(sampleFreq, channelConfig, audioMode);
//socket variables
public Socket mySocket;
private int SERVERPORT = 33333;
private static final String SERVER_IP = "172.24.1.1";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
}
public void onClickListen(View view) {
//call async task
new Listen().execute();
}
private class Listen extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
//get IP and port number
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d(debugStr, "In initial listen connect");
//create socket
mySocket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (mySocket == null) {
str1 = "Socket became null, listener";
return null;
}
//TODO here is all the new audio stuff
try {
//creates buffer to hold incoming audio data
byte [] audioBuffer = new byte[4096];
//creates input stream readers to read incoming data
BufferedInputStream myBis = new BufferedInputStream(mySocket.getInputStream());
DataInputStream myDis = new DataInputStream(myBis);
Log.d(debugStr, "Input created, listener");
// Read the file into the music array.
int i = 0;
//TODO unsure of while loop condition
while (myDis.read() != -1) {
//since incoming audio is unknown size, use estimated buffer size
audioBuffer[bufferSize-1-i] = myDis.readByte();
i++;
}
//create audio track object
AudioTrack myAudioTrack = new AudioTrack(streamType, sampleFreq, channelConfig, audioEncoding, bufferSize, audioMode);
//TODO write audio data to somewhere?
//TODO should this be in a while loop for live stream?
//TODO will this actually play the audio?
myAudioTrack.write(audioBuffer, 0, bufferSize);
//close input streams
myDis.close();
myBis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
mySocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
}
}
}
I don't think my while loop condition is correct, or if that is even the correct way to read data from an input stream. I also think that the audioTrack.write should be in the while loop, if that does actually make audio play.
Any help or clarification is greatly appreciated!
I figured it out.
byte [] audioBuffer = new byte[4096];
//creates input stream readers to read incoming data
BufferedInputStream myBis = new BufferedInputStream(mySocket.getInputStream());
DataInputStream myDis = new DataInputStream(myBis);
Log.d(debugStr, "Input created, listener");
AudioTrack myAudioTrack = new AudioTrack(streamType, sampleFreq, channelConfig, audioEncoding, bufferSize, audioMode);
//Log.d(debugStr, String.valueOf(mySocket.getInputStream().read(audioBuffer)));
Log.d(debugStr, "track made");
// Read the file into the music array.
int i = 0;
//TODO unsure of while loop condition
while (mySocket.getInputStream().read(audioBuffer) != -1) {
audioBuffer[audioBuffer.length-1-i] = myDis.readByte();
myAudioTrack.play();
myAudioTrack.write(audioBuffer, 0, audioBuffer.length);
i++;
}
//close input streams
myDis.close();
myBis.close();

Android TCP multicast missing message

I build a TCP multicast chat application using asynctask.
I am also trying to order the message in FIFO and causal order.
However, when I try to send a lot of messages simultaneously for testing, it misses some messages but I can't find the reason.
I have tried as hard as I can to improve the performance of the program because I thought the performance could be the reason. but still having the same issue.
I attached some important part of my code.
Most of all,
private class ServerTask extends AsyncTask<ServerSocket, String, Void> {
#Override
protected Void doInBackground(ServerSocket... sockets){
ServerSocket serverSocket = sockets[0];
Socket socket = new Socket();
try {
while(true) {
socket = serverSocket.accept();
InputStream inputstream = socket.getInputStream();
DataInputStream in = new DataInputStream(new BufferedInputStream(inputstream));
String msg = ""+in.readUTF();
String time = ""+in.readUTF();
String temp = time+"||"+msg;
publishProgress(temp);
in.close();
}} catch (IOException e) {
e.printStackTrace();
} finally{
try {
socket.close();
serverSocket.close();////
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Here is onProgressUpdate.
protected void onProgressUpdate(String...strings) {
/*
* The following code displays what is received in doInBackground().
*/
String strReceived = strings[0].trim();
TextView remoteTextView = (TextView) findViewById(R.id.textView1);
remoteTextView.append(strReceived + "\t\n");
try {
sequencer(strReceived);
} catch (ParseException e) {
e.printStackTrace();
}
return;
}
}
..
private class ClientTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... msgs) {
Date currentDate= new Date();
Timestamp time = new Timestamp(currentDate.getTime());
Message temp = new Message(myPort, msgs[0], time);////
try {
for(int i = 0; i <= 2; i++) {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),
Integer.parseInt(REMOTE_PORTS[i])), 1000);
socket.setTcpNoDelay(true);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream o = new DataOutputStream(new BufferedOutputStream(outputStream));
o.writeUTF(msgs[0]);
o.writeUTF(""+time);
o.flush();////
socket.close();
}
}
catch (UnknownHostException e) {
Log.e(TAG, "ClientTask UnknownHostException");
} catch (IOException e) {
Log.e(TAG, "ClientTask socket IOException");
}
return null;
}
Can you find the part causes the problem?
Sequencing / Queueing /Acknowledgement all these things are part of TCP so it is done by the protocol itself so you do not need to do all those explicitly from your code. There are still some parts of your code that can be improved. Like:
String time = received.split("\\|\\|")[0];
String msgToSend = received.split("\\|\\|")[1];
//Instead of doing this, its better to do this:
String peices[]=received.split("\\|\\|");
String msgToSend=peices[1];
String time=peices[0]
Also you can check if you are receiving all the raw messages and if its during the parsing process the messages are getting lost using a log:
Log.d("RAW_MESSAGE","Message Received: "+temp); //in your doInBackground
If you get all the messages that you send in this log, then there is nothing wrong with the protocol or the sending/receiving process rather there is a problem while you are processing the message. Also for these types of use-cases, try using the Service component rather than AsyncTask.
I hope this helps.
First of all multicast is over UDP, not TCP.
And if you want to create a multicast app, you should use multicastsocket
http://developer.android.com/reference/java/net/MulticastSocket.html

Trouble receiving data from Android Bluetooth connection

I have an android application connected to a Bluetooth mate silver chip. I'm in the process of testing the send/receive function of it. Mostly I have been following the bluetooth examples on the android dev site.
I can tell sending data works because when I write("$$$") to the chip, it enters command mode and flashes it's status LED very quickly. When the chip enters command mode, it sends a reply: "CMD". I am having trouble receiving this reply.
When I press a button, the following code is executed. mct is the global ConnectedThread that I am using to read and write. As poor form as it is, all functions are inside MainActivity.java
if(connected){
if (cmdMode == false){
mct.write("$$$".getBytes()); //enter command mode
mct.listen();
TextView lbl_history = (TextView) findViewById(R.id.lbl_history);
lbl_history.setText(message);
cmdMode = true;
}
else{
mct.write("k,\n".getBytes()); //kill the connection
cmdMode = false;
}
}
My communication thread:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void listen() {
handled = false;
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
reply=null;
while (reply==null) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
reply = buffer.toString();
//message is a global String to store the latest message received
message = reply;
} catch (IOException e) {
break;
}
}
reply = null;
}
//write and cancel functions removed for simplicity
}
When I run this code, the result is a textview that says "[B#415f8910", which I assume is junk. Multiple runs of the same code will produce similar results, with the last few digits varying. The expected result would be "CMD". Any ideas on what the problem is here? I am new to android development, so any help is appreciated.
Further inspection reveals that multiple runs strictly increase "[B#415f8910", leading me to believe that it is a memory address. Still, I don't know What to do with it though.
I found the problem. Rather than straight up calling "toString()" on the array of bytes, I needed to call the String constructor to properly convert the data:
String message = new String(buffer, "UTF-8");
specifying UTF-8 is what made the difference.

Bluetooth data transfer between two Android devices

I have been following this Android guide for Bluetooth communication
To explain exactly what I want to do, when the two devices are paired, two different activities open up on each device (server and client) where on the server activity I have different buttons, and on the client activity there is just a textview.
I want to be able to press a button on the server device and display it on the client.
I have managed to establish a connection between the two devices, but now I want to send data which I have not been able to do.
They give this code for data transfer:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // 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);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
But this line generates an error
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
And is not explained in the guide. I don't know what the mHandler is or does.
Apart from the error, I don't even really understand where to put this code. Should it be in the second activities (server and client) that I open or in the main? If in the Server activity, should it be in the onClick method for all the buttons with a different byte code to send for each button? And in this code, how do we distinguish who is sending and who is receiving?
Check out the BluetoothChat example that Google provides in the SDK. It'll show you how to implement basic sending of text over bluetooth.
You can also try the tutorial example here
Can you please describe the error as seen by you?
As informed by Ankit and Addy, BlueToothChat is the best code for you to refer. Conduct an experiment by loading it on 2 android devices - use one as server other as client to exchange the messages between them. Such experiment will help you to understand it's code and decide your coding logic.
mHandler is used for passing message from your BluetoothHandle.java to your Activity. This will help you to update messages on your screen which are returned by BluetoothHandler.
you have to create mHandler from your activity and call your handler like this -
mBluetoothHandler = new BluetoothHandler(this, mHandler);
and your BluetoothHandler.java has constructor like this -
public class BluetoothHandler {
public BluetoothHandler(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
mcontext = context;
}
}
For more details, please refer Android sample project of Bluetooth Chat .
You can also use this link :
http://myandroidappdevelop.blogspot.in/2013/05/bluetooth-chat-example.html
// Enter code here
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
break;
}
}
};

Categories

Resources