Android bluetooth connection doesn't close after application crash - java

i'm using SPP profile for connect to my device:
Set<BluetoothDevice> devices = ba.getBondedDevices();
for(BluetoothDevice bd : devices)
{
String name = bd.getName();
if(name.equals("CELLMETER"))
{
try
{
BluetoothSocket bs = bd.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
bs.connect();
} catch (IOException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
All seems okay, i created function where i'm closing input output buffers and close socket.
But when application crashes or i'm stopping application when breakpoints arrives socket doesn't closes, even after i kill process manually and it's not avalible for new connection from new instance of app.
What i'm doing wrong? For each crash/debug operation i have to reboot phone :(
It's manifested only to Android 2.3.5 (Samsung 5830i) and on Android 4.0.4 (Freelander P10). On my Android 4.2.1 (Galaxy Nexus) all okay, after app crash connection closes automatically. (it seems because there is new Bluetooth stack)

I can see 2 options to work that out:
1- Add an UncaughtExceptionHandler in your app, best in Application-derived class:
mUEHandler = new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException(Thread t, Throwable e)
{
// Close any opened sockets here
defaultUEH.uncaughtException(t, e);
}
};
Thread.setDefaultUncaughtExceptionHandler(mUEHandler);
But that only takes care of app crashes. If user kills the app, won't get in there at all.
2- Store some socket identification that allow you to close it when app restarts.
It's not perfect, but that could work-around your issue.

I solved this problem by letting my BluetoothSockets be managed by a Service running in its own process. I open, close, read, and write the sockets by passing Messages to and from the Service. If the app crashes, the Service shuts down cleanly, closing the sockets. (It does not shut down cleanly if it's running in the same process as the app.)

Related

Establishing WearOS webSocket connection when smartwatch not charging

I have a wear-os standalone application written in java, which connects as client (org.java_websocket.client.WebSocketClient) via WLAN websockets to a server (org.java_websocket.server.WebSocketServer) running on the smartphone (TicWatch Pro 3). When I run the code, everything works fine (web sockets connect) as long as the smartwatch is charging. As soon as I disconnect the charger and try to connect the smartwatch client via websockets to the smartphone server no connection can be established. No error is shown, there is simply no connection established.
This is a simplified version of the Runnable class used to start the web socket client.
public class BackgroundReceiverThread implements Runnable {
public static void startBackgroundReceiver(){
AsyncTask.execute(new BackgroundReceiverThread());
}
private BackgroundReceiverThread() {}
//#Override
public void run() {
try {
client=new BackgroundReceiverClient(new URI("ws://localhost:8887"));
client.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
The BackgroundReceiverClient class looks the following:
public class BackgroundReceiverClient extends WebSocketClient {
public BackgroundReceiverClient(URI serverUri) {
super(serverUri);
}
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("mytag","On Open");
}
#Override
public void onError(Exception e) {
Log.i("mytag","On Error:"+e.getMessage());
}
}
When the smartwatch is charging and BackgroundReceiverThread.startBackgroundReceiver() is invoked, the onOpen() method is invoked. When the charger is disconnected the onOpen() method is not invoked.
I assume this is due to energy saving precautions of the smartwatch, which are activated when not charging. I have already tried to identify the respective setting on the smartwatch but couldn't find it.
How can I get the client connecting to the server when the smartwatch is not charging?
I had a fairly similar problem, I was trying to connect via Socket.IO with my Ticwatch E2 and it only worked when charging. After searching for all kinds of energy saving precautions that I could disable the real problem after all was this:
My Ticwatch automatically connects with my phone via Bluetooth and uses the wi-fi my phone is connected to through my phone (You can see the connection status in the Wear OS app on your phone). In order to establish a Socket Connection, the watch needs to be connected to the wi-fi itself. It does not do that by default when connected to your phone.
You can easily test this hypothesis by enabling flight mode on your phone and try the application on your Ticwatch again, it worked for my socket.IO application.

How to connect with a Bluetooth device without pairing

I'm currently developping my first app in java.
This app requires a direct connection with my BL652, which doesn' t accept any kind of pairing option. That being said, I'm stuck with the code below, which still tries to pair with my bluetooth device instead of just connecting. Therefore, I wanted to know what am i supposed to do in order to make a connection that doesnt require pairing.
Thanks in advance for any response.
String mac_address = "DA:72:21:29:0F:F0";
private static final UUID MY_UUID = UUID.fromString("E54B0002-67F5-479E-8711-B3B99198CE6C");
lvNewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
BluetoothDevice device = (BluetoothDevice) mBluetoothAdapter.getRemoteDevice(mac_address);
try {
socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
I'm not sure about connection to external hardware but it's definetly possible to connect 2 phones without pairing. I made it using Android Nearby Connections . And yeah it's basically working with BLE. As far as I know it's possible to connect to RaspberryPi using that API.
Bluetooth devices can be made to communicate with each other using master-slave configuration. I first tried with two BLE-HC05s, made one as master and the other as slave, and as expected the master is able to send data, slave is able to receive data, that can be seen using the Serial Monitor in Arduino IDE. I have developed a similar app, which connects to a BLE-HC05 device, sends and receives data. But since you are trying to get data or send data to the App on your phone, Android will not support such unpaired anonymous communications. If you are having trouble with connection or pairing Bluetooth device and your app, I may help you with that. But as far as Bluetooth communication without pairing is concerned, you may not be able to find a way.
Edit: The code to connect any bluetooth device, like BLE-HC06 as you have mentioned, is 1234 (Only if you have not changed it)

How to keep beacon in pairing mode until it comes out of range for android?

I am developing an application to communicate with beacon. It display all the names of beacons, I have to pair & connect to beacon on onclick event.I need to keep beacon in connecting mode until it goes out of range. But in my case it disconnects after certain amount of time.Please tell me how to keep beacon in pairing mode until it comes out of range.
Below is my code for pairing beacon to android app.
private void pairDevice(BluetoothDevice device) {
try {
Method method = device.getClass().getMethod("createBond", (Class[]) null);
method.invoke(device, (Object[]) null);
} catch (Exception e) {
e.printStackTrace();
}
}
It is common for Android Bluetooth LE connections to disconnect before you are finished communicating, so you must build logic into your app to handle these disconnect events and retry the connection as needed.
If you Bluetooth LE beacon is exiting connectable mode before you can do this, then you must somehow extend the time it is in this mode. How you do this is (if it is possible at all) is manufacturer-specific, so you'll have to consult your beacon manufacturer's documentation on how you put the beacon into configurable mode.

How to handle data roaming when you use sockets in Android?

I'm programming a game in Android that uses AI, which requires big CPU power, that a normal Android device just doesn't have. So I decided to write a server in Java using sockets that will calculate everything and return a value to the client (the android device).
Now, I'm used to program for PC, but not for phones. In mobile, the IP of the device can change back and forth due to data roaming and WIFI.
My question is, how do you handle a changing IP? How do you tell a new connection is the same device? Or maybe the Android device does all of that automatically?
I'm new to stackoverflow, I hope I didn't ask too many questions. :)
Thank you very much for your answers!
You don't need to handle ip changing at all. A client(an android device) must know server host/ip and reconnect if it was disconnected from network, nothing more.
private static class ConnectionTask implements Runnable {
private boolean connected;
#Override public void run() {
try {
InetAddress serverAddress = InetAddress.getByName("host");
Socket socket = new Socket(serverAddress, 9999);
connected = true;
while (connected) {
// sending or writing data
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
//here you lost the connection due to some reason
//you need to notify user about the problem and wait for connection
}
}
}
To receive event about network state you need to register receiver:
context.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (isNetworkAvailable()) {
unregisterReceiver(this);
tryToConnect();
}
}
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
Okay guys I figured out a way, thank to Fox in socks' answer.
Each time a user connects to the server socket, you take his UUID (or an hashed version of it, if you want more security :P ).
Then, when that user disconnects for some reason and tries to connect to the server socket again, he'll send the same UUID. That way, you can tell both of the connections are the same, and continue with the processing.
For more information about UUID, look here:
Is there a unique Android device ID?
Thank you all! :)
Now how do I mark this question as a closed one? :P

Bluetooth Socket [isConnected()]

I have 3 activities that uses Bluetooth Connection/Communication.
On my first page, I connect to a bluetooth device already. When I move to another activity, I tried using this code:
BluetoothSocket btSocket;
try{
if(btSocket.isConnected(){
System.out.println("connected");
}
}
catch (Exception e{
}
I did not get anything in my Logcat at all and the Activity did not crash too. I'm not sure on how to use a Thread/Runnable for this Bluetooth Connection to stay in connection through activities and such. So I was thinking if this is possible?
Thanks.
Your current approach seem to fail with an NullPointerException, which will be catched by your Exception-Block. I would suggest you to implement a Background service which will handle the BT-connection in background. A sample could be found on the bottom of this page: http://developer.android.com/guide/topics/connectivity/bluetooth.html (Related Samples)
That is because you are ignoring the Exception that btSocket is null.
try
catch (Exception e{ e.printStackTrace ();
}
You will need to finad a way to pass you active Bluetooth connection to this method/activity.

Categories

Resources