gpslogger icon indicating copy to clipboard operation
gpslogger copied to clipboard

Custom URL does not work if Wifi/Mobile data is not enabled, but bluetooth PAN is available

Open rotarurazvan07 opened this issue 11 months ago • 4 comments

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 :)

rotarurazvan07 avatar Feb 04 '25 19:02 rotarurazvan07

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".

mendhak avatar Feb 04 '25 20:02 mendhak

I can try this tomorrow, without constraints. Thanks a lot. I will report back :)

rotarurazvan07 avatar Feb 04 '25 21:02 rotarurazvan07

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.

nckpln avatar Feb 10 '25 11:02 nckpln

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.

mendhak avatar Feb 11 '25 19:02 mendhak