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.
Related
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)
I am recently working on a project that requires sending a command from my android mobile app to the android things on my raspberry pi 3. How can I achieve this through a WiFi connection?
I only need to send a String to the device.
If one of your devices isn't connected to internet, you could :
Option 1 :
use Google Nearby Connections API , the API choose the best way to communicate (eg: Bluetooth, Wifi...).
See https://github.com/googlesamples/android-nearby/tree/master/connections
Option 2 :
Use Socket to communicate but your devices need to be on the same network. If they aren't connected to the same network, you can connect them using WIFI P2P.
Using Android Things, you can use the Nearby Messages API, which gives you the ability to communicate to and transfer messages between two Android devices within their apps. Here's a code snippet:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mMessageListener = new MessageListener() {
#Override
public void onFound(Message message) {
Log.d(TAG, "Found message: " + new String(message.getContent()));
}
#Override
public void onLost(Message message) {
Log.d(TAG, "Lost sight of message: " + new String(message.getContent()));
}
}
mMessage = new Message("Hello World".getBytes());
}
#Override
public void onStart() {
super.onStart();
...
Nearby.getMessagesClient(this).publish(mMessage);
Nearby.getMessagesClient(this).subscribe(mMessageListener);
}
#Override
public void onStop() {
Nearby.getMessagesClient(this).unpublish(mMessage);
Nearby.getMessagesClient(this).unsubscribe(mMessageListener);
...
super.onStop();
}
If you use system like Raspbian you can transform your Raspberry into a server.Then, You will have different ways to send your command:
Option 1: Set up an Http server on your raspberry (PHP, NodeJS, JEE, ...) and send command via HTTP Request.
Option 2: Set up a Socket Server on your raspberry (Socket.io, raw socket, ...) and send command via socket client
Option 3 Set up MQTT Server on your raspberry and send command via MQTT client (this last option is the way to go when talking about Internet of Things). Note that the program which receive command should implement MQTT Client as MQTT is based on pub/sub pattern.
You can use nanoHttpd on Android things and other library such as retrofit or volley on the Android device.
Check out this example for controlling a car via an Http API: https://github.com/plattysoft/IotCar
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
I want to create a super basic Android App that connects to a python server running on my PC but the python server never gets the connection
my java code:
public class WriteToSocket {
Socket sock;
public void Test() {
try {
this.sock = new Socket("PCName", 9871);
} catch (UnknownHostException e) {
System.out.println("Unknown host: PCName");
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
}
public void Test1(){
try {
this.sock.close();
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
}
and
public void onClick(View v) {
WriteToSocket a = new WriteToSocket();
a.Test();
}
and my python server is
import socket
sock = socket.socket()
name = "PCName"
port = 9871
sock.bind((name,port))
sock.listen(1)
s,a = sock.accept()
I expected after the button click for the python server to accept the connection (I also tried changing "PCName" to "127.0.0.1")
I've looked around but nothing helped me so far :S
Bind your server socket to one of the IP addresses of your PC which is accessible from your android, and not to 127.0.0.1. Or alternatively bind it to all available interfaces (0.0.0.0).
Then connect from your android to that IP.
E.g. if your PC has IP address 1.2.3.4 then use this IP in both applications.
Use netstat to see if the port is really open on your PC.
Check to see if your android application has the permission to use the internet (specified in the manifest: "USES_INTERNET" or something like that).
Also your python script discards the connection as soon as it is made.
In python change bind address to 0.0.0.0. It will bind for all IPs attached to your machine. Then in android app change to correct IP of your computer.
IP 127.0.0.1 is a loopback and you can't connect to it from outside of the system.
The android phone doesn't know what PCName is, change "PCName" in the python code back to '127.0.0.1', then in the android project put in the local IP address of the server.
This of course assuming that both the phone and the server are on the same local network.
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.)