3

I am trying to keep a tcp connection to a server alive even while the phone goes into sleep mode. I have searched everywhere and tried everything. This problem occurs on some phones and not others which is kind of random.

So basically one client sends a request to the server, then the server sends the request to another client. What happens is that the receiving client doesn't get the request at all. I have tested this with a debugger and the next line of code after the read never gets called. It is important for the device to receive the message right away. I am wondering how viber is achieving this. I thought about google cloud messaging but i would have to re-implement a lot, also according to the documentation, even with google cloud messaging the message doesn't necessarily reach the destination right away.

here is my code:

 class BackgroundReadThread extends Thread {

    @Override
    public void run()
    {
        while(connectedToServer)
        {
            try
            {
                int bytesRead=0;
                if(myWifiLock!=null && !myWifiLock.isHeld())
                    myWifiLock.acquire();
                byte val=(byte)myInputStream.read();
                myWakeLock.acquire();//this line never gets called when in sleep
                if(val==-1)
                {
                    unexpectedDisconnectionFromServer();
                    if(myWifiLock!=null && myWifiLock.isHeld())
                        myWifiLock.release();
                    myWakeLock.release();
                    return;
                }
                bytesRead=myInputStream.read(myBuffer, 0, bufferSize);
                if(bytesRead<1)
                {
                    unexpectedDisconnectionFromServer();
                    if(myWifiLock!=null && myWifiLock.isHeld())
                        myWifiLock.release();
                    myWakeLock.release();
                    return;
                }
                byte[] dataArray=Arrays.copyOfRange(myBuffer,0,bytesRead);
                ByteBuffer data=ByteBuffer.allocate(bytesRead+1).put(val).put(dataArray);
                myParent.invokeReceiveAction(data, bytesRead+1);
            }
            catch (IOException e)
            {
                myWakeLock.acquire();
                unexpectedDisconnectionFromServer();
                e.printStackTrace();
            }
            finally
            {
                if(myWifiLock!=null && myWifiLock.isHeld())
                    myWifiLock.release();
                if(myWakeLock!=null && myWakeLock.isHeld())
                    myWakeLock.release();
            }
        }
    }
}

EDIT: forgot to mention that this code is running in a service

Marian Paździoch
  • 8,813
  • 10
  • 58
  • 103
Maro
  • 253
  • 3
  • 8
  • `the next line of code after the read never gets called`, which means the code is blocking at the network IO read call. Do you have socket timeout ? If so, what's the timeout, and has it timed out atleast by once? – nmxprime Jan 12 '15 at 08:17
  • Is the service set as Forground? – nmxprime Jan 12 '15 at 08:17
  • @nmxprime i do have a timeout of 6 minutes but the keep alive interval on the server side is 5 so as long as the server is up the read timeout should never trigger and it doesnt because the device falls into sleep. it only triggers when i wake the device after more than 6 minutes have passed so even if like say 10 min have passed without a receive it wont trigger unless i wake the screen. The service runs in the background. – Maro Jan 12 '15 at 08:32
  • If the service runs in the background, Android would likely pause it. Hence the thread you're calling the network read may not be scheduled to run. Have you tried starting forground the service? – nmxprime Jan 12 '15 at 08:38
  • I have a similar situation. For my case, the server keep alive timeout is indefinite, hence my devices kept the socket connected apparently more than 6 hrs. – nmxprime Jan 12 '15 at 08:39
  • @nmxprime running the service in the foreground could drain the battery. The device is supposed to wakeup during a short period of time when it receives information on a socket. If i set the keep alive timeout infinite the tcp connection will in fact hold but the device will never receive anything while it is in sleep mode so no action will be taken. In your situation does your device receive anything while it is in sleep mode? – Maro Jan 12 '15 at 08:45
  • It doesn't received. My target was to keep the connection alive. Yes I agree, forground services drain battery. – nmxprime Jan 12 '15 at 08:48
  • Have you found any way around, or the cause ? – nmxprime Jan 19 '15 at 06:15
  • @nmxprime i am actually more confused now. I tested my application with 2 more phones and they both worked. And even on my phone some days it works and other days it doesnt. What phone have you tested yours on? And do you also acquire a wakelock once you receive data? – Maro Jan 19 '15 at 10:43
  • I have tested in Samsung GT-I9300, I have no use of power wakelocks, only wifi lock is used – nmxprime Jan 23 '15 at 05:01

1 Answers1

1

I have no idea why but the problem only occurs sometimes and it only occurs on the debug version of the application. I have tested the release version of the application and it never failed once on any of the phones ive tested it on. So i guess the problem is with the debug version although i have no idea why. Hope this helps someone having similar problems.

Maro
  • 253
  • 3
  • 8