Custom URL does not work if Wifi/Mobile data is not enabled, but bluetooth PAN is available
Environement: Phone that has disabled mobile data and wifi, but has a bluetooth tetering enabled with another device that runs a flask server. Bug description: The GET request is never executed or it fails out (I haven't investigated much) My local fix: Open socket and let Android handle the connection:
BluetoothDirectClient class that has the sendRequest function
package com.mendhak.gpslogger.senders.customurl;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BluetoothDirectClient {
public static void sendRequest(
String url
) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(() -> {
URI uri = null;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
// Extract my info
String clientIp = uri.getHost();
int port = uri.getPort();
String path = uri.getRawPath();
if (uri.getRawQuery() != null) {
path += "?" + uri.getRawQuery();
}
// Write on socket, let Android handle connection
try (Socket socket = new Socket(clientIp, port)) {
OutputStream outputStream = socket.getOutputStream();
String httpRequest = String.format(
"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",
path,
clientIp
);
outputStream.write(httpRequest.getBytes());
outputStream.flush();
// Read response
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line).append("\n");
}
Log.d("Bluetooth", "Response:\n" + response);
} catch (IOException e) {
Log.e("Bluetooth", "Error: " + e.getMessage());
}
handler.post(() -> {
//UI Thread work here
});
});
}
}
Then, I called it in GpsLoggerService at onLocationChanged, as i couldn't reach the doWork function inside the CustomUrlWorker
String url = "http://IP:PORT/PATH?lat=%LAT&long=%LON&alt=%ALT&time=%TIME";
url = url.replace("%LAT", String.valueOf(loc.getLatitude()));
url = url.replace("%LON", String.valueOf(loc.getLongitude()));
url = url.replace("%ALT", String.valueOf(loc.getAltitude()));
url = url.replace("%TIME", String.valueOf(Strings.getUrlEncodedString(Strings.getIsoDateTime(new Date(loc.getTime())))));
BluetoothDirectClient.sendRequest(
url
);
Mind you, I am in no way an Android expert, and I have not tested much my solution, just wanted to expose a limitation :)
I haven't encountered this kind of a setup before so it sounds very specific/niche to me. I don't think it's catered to in the Android WorkRequest setup.
In the app the Custom URL has a network requirement,
https://github.com/mendhak/gpslogger/blob/2d0e36caf13dbe80dc55fddc4af77a99dde4bf0d/gpslogger/src/main/java/com/mendhak/gpslogger/common/Systems.java#L330-L332
That NetworkType for either condition is from this page: https://developer.android.com/reference/androidx/work/NetworkType The purpose behind the network check is so that the jobs don't get queued up without a working connection.
And I'm assuming there must be (or hope there is) some kind of network connectivity test that happens before the system returns that connected = true.
Your local fix looks quite good, I wonder if there's a simpler way which is to remove the constraints from the builder:
https://github.com/mendhak/gpslogger/blob/2d0e36caf13dbe80dc55fddc4af77a99dde4bf0d/gpslogger/src/main/java/com/mendhak/gpslogger/common/Systems.java#L334-L337
And that could simply mean "just send it, I don't care for network connectivity".
I can try this tomorrow, without constraints. Thanks a lot. I will report back :)
Same issue here. I run into this problem when I try logging to my local web server 192.168.. through WiFi and it works perfectly fine when the internet access for this subnet is enabled on a router, but if it is not, the logging to the local server stops working. Additionally, the same thing happens if I block internet access in Android using AFWall. The issue was not present in v.130 and below.
Then for sure it must be related to WorkManager's network 'detection' logic. 131 is when Workmanager was introduced, since I had to move away from the old library.