Search code examples
androidsocketsservicetcpseekbar

Android - sending SeekBar values via TCP


I'm currently developing an android app that communicates with some other device, that acts like a server. Basically to build the application's views, I first have to send a query via a TCP connection to the server to get the info. I (successfully) execute these queries with the help of an async task:

    private class TCPQuery extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
                //connect the socket send the query and receive feedback
        }

        @Override
        protected void onPostExecute(String result) {
                //parse server feedback and build the view
        }
    }

This approach works fine when it comes to single queries that are made only a couple of times during the application's lifetime. What I have trouble implementing is the following: a certain view in the application, contains seekbars. So basically, every change of the seekbar value (every time the onProgressChange method fires) must be sent to the server(no feedback this time), so it can keep track of the actual values.

How would you go about implementing this? Of course, no networking in android may be done on the main thread. But here establishing a connection, sending a message and closing the connection every time the value changes is not acceptable. Sliding the bar only a little already results in a dozen such calls in a split second.

I've tried approaching this problem by implementing a service. The service had its own socket to communicate with the server. I would connect the socket to the server and keep it open, so that I would be able to call the service's send method any time a seekbar change has been made. But that seemed to interfere with the other queries I mentioned before (the ones executed with async tasks). I couldn't connect one while the other was active. Now I'm not sure whether my service implementation was just bad, or if I am misunderstanding a crucial networking concept here.

I have thought of only sending the data onStopTrackingTouch, but that is not really what I am after. Any help would be very much appreciated!


Solution

  • Use the system clock to check when the last query has been sent, and don't send another until a certain time has elapsed. You can change seekbar's value as you want, but the query will be sent only every X milliseconds.

    static long sendInterval = 600; //milliseconds
    
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
      long nextSend = 0;    
    }
    
    @Override
    public void onProgressChanged(......) {
      if (nextSend < uptimeMillis()) {
      ...send the query and parse feedback...
      nextSend = uptimeMillis() + sendInterval ;
      }
    

    Start with nextSend = 0, so the first time the query will be sent immediatly. Choose sendInterval value according to server's response time. Start with a high value and decrease until you see that all is working well. If the query itself and the response are small (a few bytes) consider using UDP instead of TCP, it's faster and you can use lower values of sendInterval.