Bluetoothsocket timeout on read and write - android

I'm designin an application in Android that connects the mobile to a bluetooth device. I can do this, as I open a BluetoothSocket like this:
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
Where device is the paired device with the mobile bluetooth desired. The thing is, this external device is a bit special, and it has different times for writing and answering to the mobile, so I need to put some timeouts on my socket for reading and writing, but I've searched a lot and it seems like BluetoothSocket doesn't support this.
Can anybody tell me a different way to admin timeouts on reading and writing to the port on the BluetoothSocket class for Android?
Thank you!

There are many Exceptions a socket or it's streams can throw. The socket.connect() for example can throw a ConnectTimeoutException. Every method in the BluetoothSocket context can through an IOException just take a look at the documentation and you will see which exception you have to catch in order to make your program work properly.

Here is the code for reading and writing code:
Writng code on port:
try
{
// Enviamos los bytes
DataOutputStream dOut = null;
dOut = new DataOutputStream(socket.getOutputStream());
// Send message
dOut.writeBytes(res);
dOut.flush();
}
catch (IOException e)
{
Dialogs.showErrorDialog("Error al recuperar la fecha y hora del dispositivo Nonin.", this);
}
Then, reading from port until response available:
DataInputStream dIn = null;
// We receive the answer
try
{
dIn = new DataInputStream(socket.getInputStream());
}
catch (IOException e)
{
Dialogs.showAlertDialog("An exception occured during bluetooth io stream creation", this);
}
while (true)
{
try
{
String data = dIn.readLine(); // readLine();
byte[] total = EncodingUtils.getBytes(data, "ASCII");
Dialogs.showInfoDialog("Mensaje ok: " + data.toString(), this);
}
catch (IOException e)
{
break;
}
}
The thing is that I think the writing works, as I convert the desired string into bytes, and it works. But then, when I'm waiting for response, it mixes further responses with the desired, and I think this is because timings.
There's no more code in the middle related with sockets. First, I create it. Then, I try to send a byte String. Then I wait until I receive the answer for the byte String that I just sent.
Thank you in advance.

Related

Sending bluetooth data between Android and Hololens

I have created an application to Android and Microsoft Hololens, where it is possible to send some GPS-data with bluetooth from an Android-phone to a Hololens (with Bluetooth LE Advertiser) and that works allright. But when I am trying to send other data from Hololens to Android, I have a problem that Android-phone can't discover Hololens, although these devices are paired. Is it even possible to send data from Hololens with bluetooth, or is there only something wrong in my code? Does Bluetooth LE Advertising support two-way data transfering?
I am guessing you have a BluetoothConnected thread in your android app with an InputStream (mine is mmInStream). Try using this as your 'run' function in the thread:
public void run() {
System.out.println("BT THREAD RUNNING");
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
InputStreamReader mmInStreamReader = new InputStreamReader(mmInStream);
BufferedReader mmReader = new BufferedReader(mmInStreamReader);
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
Thread.sleep(100);
String s = mmReader.readLine();
Thread.sleep(100);
//Static class that handles the response
BluetoothCommunications.responseHandler(s);
} catch (IOException e) {
System.out.println("Input stream was disconnected" + e);
main.disconnected();
break;
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

How to send a text message to a paired device through bluetooth in android?

In my app I want to send and receive text message through bluetooth. I can see in my listview a list of paired device name and address.But when I am trying to send a text to a paired device nothing happens. In other device there is no text received.
This is my Code to send message to a paired device.
private void sendDataToPairedDevice(String message, String adress) {
byte[] toSend = message.getBytes();
try {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(adress);
// BluetoothSocket socket
// =device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"));
BluetoothSocket socket = null;
Method m = null;
try {
m = device.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
} catch (Exception e) {
e.printStackTrace();
}
try {
socket = (BluetoothSocket) m.invoke(device, 1);
} catch (Exception e) {
e.printStackTrace();
}
OutputStream mmOutStream = socket.getOutputStream();
mBluetoothAdapter.cancelDiscovery();
socket.connect();
mmOutStream.write(toSend);
} catch (Exception e) {
Log.d("TAG", "Exception during write", e);
}
}
the bluetoothchat sample is actually the perfect thing to use if you are new in using the bluetooth api.
assuming that you are using only one Activity for your application which is the BluetoothChat class :
for sending text to the device you are connected to, use the "sendMessage(String message)" method in the BluetoothChat class to send text.
as for receiving and handling the text, you will find also handleMessage(Message msg) method somewhere in the bluetoothchat class then go this part:
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
see the readMessage String?
this is the text that that you receive from the other device , now you can handle it as you want.
then simply change the main layout that the BluetoothChat class refers to, then in BluetoothChat chat either comment or delete the parts that have errors which actually will be the parts in the UI u have deleted or changed.
i know the code may sound messy but this is the easiest way to use it quickly as possible and watching video tutorials or text tutorials for hours will just make it more complicated, believe me i tried this before.

Connecting Bluetooth in Android

I have done a simple app to connect my phone with an Arduino via BT and all goes right. My phone have Android 2.3.6... But, when I try the app on my tablet (with android 4.0.3), I can't connect. I post here the specific piece of code:
try {
BluetoothSocket socket = mydevice.createRfcommSocketToServiceRecord(UUID.fromString(ARDUINO_STANDAR_UUID));
socket.connect();
OutputStream output = socket.getOutputStream();
InputStream input = socket.getInputStream();
Log.d(TAG, "Connected");
}
catch (IOException e) { Log.e(TAG, e.getMessage()); }
}
Using the Log, the problem is at socket.connect(); at that point, I have to enter the PIN of the device, but it don't connect anyway... The error is "Connection refused"...
What can be wrong?
Try something like this to take care of the connection. I just updated an old android-10 app the other day to android-17 and dealt with exactly this.
BluetoothDevice yourDevice;
try {
Method m = yourDevice.getClass().getMethod( "createInsecureRfcommSocket", new Class[] { int.class } );
selectedDeviceSocket = (BluetoothSocket) m.invoke( yourDevice, Integer.valueOf( 1 ) );
selectedDeviceSocket.connect();
}

Android Serversocket does not seem to accept connections on emulators

I've been trying to implement a simple socket communication between two Android emulators but just can't seem to get it.
My server:
public void run() {
if (SERVERIP != null) {
try {
serverStatus.setText("My IP: " + SERVERIP);
serverSocket = new ServerSocket(6798);
serverStatus.setText("ServerSocket Created");
}
catch(Exception e) {
e.printStackTrace();
}
try {
while (true) {
serverStatus.setText("waiting for client");
Socket client = serverSocket.accept();
serverStatus.setText("Connected.");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = in.readLine();
serverStatus.setText(line);
in.close();
client.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
else
serverStatus.setText("Couldn't detect internet connection.");
}
My Client:
try {
InetAddress ina = InetAddress.getByName("10.0.2.2");
socket = new Socket(ina, 6789);
}
catch (Exception e) {
e.printStackTrace();
}
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Hey Server!");
dispText.setText("sent");
}
catch (Exception e) {
e.printStackTrace();
}
The Client side goes on to display the message "sent" however the Server does not move beyond "waiting for client" (stuck on the blocking accept()).
I've used telnet on my Windows machine to redirect port 6789 to 6798 on the server emulator's console. I've also tried turning off my firewall and the other suggestions posted on the similar questions asked here. Please help as just can't seem to get it and feel like I'm making a very stupid mistake.
Also, can anyone please tell me how it is possible for the Client to move beyond the Socket creation code line if the Server is still stuck on accept(). Or, does it not matter to the client that the Server isn't responding as long as it is listening on the port??
Android emulators are placed behind a virtual firewall/router by design, and cannot see each other, even when they are on the same network. The "Using Network Redirection", as well as "Interconnecting Emulator Instances" part of Google's doc on the emulator explains how to communicate with an emulator instance.
As for your last question. Use the empty constructor for socket, and then use the connect call with a specified timeout.

RFCOMM connection between two Android devices?

I have two Android devices which I want to connect, using Bluetooth, and transfer data over an RFCOMM channel. I only one one device to receive data, while the other device sends it...
Using this code, I am able to connect to the other device and begin listening to an RFCOMM channel:
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(device, 2);
socket.connect();
class BasicThread implements Runnable{
public void run() {
try {
InputStream stream = socket.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stream));
while (true){
Log.d("myapp", "now listening...");
latestLine = r.readLine();
Log.d("myapp", latestLine);
}
} catch (IOException e) {
}
}
}
new Thread(new BasicThread()).run();
Using the other device, I have implemented a listening socket like this:
Method m = blue.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
BluetoothServerSocket socket = (BluetoothServerSocket) m.invoke(blue, 2);
BluetoothSocket sock = socket.accept();
Log.d("myapp", "Connected...\n\n\n\n\n\n\n\n");
OutputStream s = sock.getOutputStream();
final PrintWriter out = new PrintWriter(s);
They both connect on RFCOMM channel 2, and both SEE eachother, however, the second device always remains blocked at the BluetoothSocket sock = socket.accept();
Any help?
OK, I am newbie, but I can try to help. So here is my experience, I managed to connect two devices using reflection. My Android phone is receiving data using method listenUsingInsecureRfcommOn, while other devices are masters in communication and send the data over BT SPP. I had a problem with this method since it makes no visible SDP record, so I could not detect it with other devices. Because of that, I made small sniffer using Bluecove and Java SE that tries to connect to every port in given range. Here's the code:
package application.test;
import static java.lang.System.out;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
public class RfCommClient {
public static void main(String args[]) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
String add = "btspp://8C71F894A36D:";
String par = ";authenticate=false;encrypt=false;master=true";
String url = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd;HH-mm-ss-SSS");
for (int i = 1; i < 15; ++i) {
try {
url = add + i + par;
out.format("Time: %s, port = %d\n", sdf.format(System.currentTimeMillis()), i);
StreamConnection conn = (StreamConnection) Connector.open(url);
PrintStream ops = new PrintStream(conn.openOutputStream());
ops.println("Hi there...");
// response
Thread.sleep(1000);
InputStream is = conn.openInputStream();
byte[] resp = new byte[5];
int r = is.read(resp);
out.println("r = " + r + ", response = " + new String(resp, "US-ASCII"));
Thread.sleep(10 * 1000);
conn.close();
} catch (Exception e) {
out.println("Exception occured, time = " + sdf.format(System.currentTimeMillis()) + ", i = " + i);
//e.printStackTrace();
}
}
}
}
What I've learned it that some ports are taken, and that some ports can not be uses (as documentation says, e.g. port 0). For example, port 2 I believe was taken, because when I send some data to it I receive 5 chars back beginning with ERR :).
While, on the other hand, my thread is still waiting?! :)
That leads us to another thing I noticed, ports (or channels) are not always mapped to desired number. For example, to me often happened that I want to send something on port 15, but on Android, thread waiting on port 9 received the data :)
So I suggest, check which port is really allocated!
You can achieve that using the code I posted.
And another thing, here is a link to channelPicker function, which selects channel when ordinary API is used, if I am not mistaken, inside some constants should represent reserved channels.
I just noticed something, my code for registering port is slightly different, here is how I do it:
Method m = cba.getDeclaredMethod("listenUsingInsecureRfcommOn", int.class);
ss = (BluetoothServerSocket) m.invoke(BluetoothAdapter.getDefaultAdapter(), port);
Anyway, I know that this is probably too late, but, maybe someone in future has similar question.

Categories

Resources