Search code examples
androidadbandroid-volleyusb-debugging

Volley local request only works when attached to USB debugging


I'm building an app that acts as an proxy between a measurement device and a web app. This is necessary because the measurement device doesn't offer CORS / HTTPS implementations and cannot be called directly from the web app.

This works by creating a hotspot with my phone and connecting the measurement device to it. We then run a background service which hosts a RouterNanoHTTP server instance. This instance basically just forwards the call to the measurement device.

My app works perfectly fine when connected to the USB with the computer. However, the second I unplug the USB cable all requests to the measurement device return a Volley timeout error. I've tried multiple things, including setting the binded network adapter manually. The measurement device is still reachable from my phone's browser. Therefore, I think it's more a configuration error of some kind than a code error.

I've the INTERNET and ACCESS_NETWORK_STATE in my AndroidManifest.

Edit: it seems that it might have to do with my implementation of the HttpServer. I've added a button in my view to call the API, and that still works when disconnected from the USB. However, any requests that come via the HttpServer aren't working anymore.

Relevant code:

override fun getUrl(url: String, callback: (result: String?) -> Unit) {
    val req = StringRequest(
        Request.Method.GET, url,
        Response.Listener<String> { res -> callback(res) },
        Response.ErrorListener { err ->
            Log.d("MD-ERROR", err.toString());
            callback(null)
        }
    )

    req.retryPolicy = DefaultRetryPolicy(
        5000,
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
    )

    this.requestQueue.add(req)
}

HTTP server:

class HttpServerWrapper(private val port: Int, private val xrfConnector: IXrfConnector) : AsyncHttpServer() {

/**
 * Starts the server
 */
fun startServer() {
    this.addMappings()
    this.listen(this.port)
}

fun addMappings() {
    this.get("/") { _, response: AsyncHttpServerResponse ->
        response.headers.add("Access-Control-Allow-Origin", "*")

        this.xrfConnector.getMeasurements {
            val gson = Gson()
            val json = gson.toJson(it?.measurements)

            response.send(json)
            response.end()
        }
    }
}

Output from VolleyDebug (first request is with USB connected, second without):

2021-01-19 10:21:03.037 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (785  ms) [ ] http://192.168.43.9:8080/xapi/measurements?startDate=2021-01-12 0x676a9949 NORMAL 2
2021-01-19 10:21:03.038 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+0   ) [1621] add-to-queue
2021-01-19 10:21:03.040 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+1   ) [1613] cache-queue-take
2021-01-19 10:21:03.043 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+4   ) [1613] cache-hit-expired
2021-01-19 10:21:03.045 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+2   ) [1616] network-queue-take
2021-01-19 10:21:03.049 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+583 ) [1616] network-http-complete
2021-01-19 10:21:03.062 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+16  ) [1616] network-parse-complete
2021-01-19 10:21:03.065 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+4   ) [1616] network-cache-written
2021-01-19 10:21:03.068 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+0   ) [1616] post-response
2021-01-19 10:21:03.069 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+175 ) [ 2] done
2021-01-19 10:21:11.193 26316-26432/my.app.bridge I/System.out: http://192.168.43.9:8080/xapi/measurements?startDate=2021-01-12
2021-01-19 10:21:11.201 26316-26422/my.app.bridge D/Volley: [1613] WaitingRequestManager.maybeAddToWaitingRequests: new request, sending to network http://192.168.43.9:8080/xapi/measurements?startDate=2021-01-12
2021-01-19 10:21:26.390 26316-26316/my.app.bridge D/XRF-ERROR: com.android.volley.TimeoutError
2021-01-19 10:21:26.425 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (15229 ms) [ ] http://192.168.43.9:8080/xapi/measurements?startDate=2021-01-12 0x676a9949 NORMAL 3
2021-01-19 10:21:26.428 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+0   ) [1621] add-to-queue
2021-01-19 10:21:26.434 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+1   ) [1613] cache-queue-take
2021-01-19 10:21:26.439 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+5   ) [1613] cache-hit-expired
2021-01-19 10:21:26.441 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+4   ) [1615] network-queue-take
2021-01-19 10:21:26.443 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+5104) [1615] socket-retry [timeout=5000]
2021-01-19 10:21:26.448 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+10080) [1615] socket-timeout-giveup [timeout=10000]
2021-01-19 10:21:26.450 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+0   ) [1615] post-error
2021-01-19 10:21:26.455 26316-26316/my.app.bridge D/Volley: [2] MarkerLog.finish: (+35  ) [ 2] done

Solution

  • So, it seems the problem was battery optimization which was enabled for the app. After disabling this, the requests came through without a problem.

    The only thing that is weird that you don't get any errors or logging that your request is blocked. I only found out by this line after using another HTTP library:

    2021-01-25 12:02:53.881 4942-1564/system_process D/ConnectivityService: Returning BLOCKED NetworkInfo to uid=xxx
    

    There goes a week of debugging :D.