(sorry for bad english) I'm developing app for android tv/set-top box (STB). I have problem with some devices, others work fine. I hope that someone encountered something similiar or can point me in right direction.
I use background service to periodically check for some data on our server. I use retrofit2 with okhttp3 for network communication. But after 10 minutes, retrofit starts returning this exception:
IOException java.net.SocketTimeoutException: failed to connect to our.server.org/XX.XX.XXX.XXX (port 80) after 15000ms
My first idea was, that it is what it says, that server lost connection. So I have tried to ping it from my computer, everything OK. Next, I have checked STB, connection was working. I've build another app, this one with Activity, View, and Button. On button click, it sends same request as that background service. This works without problem. So it seems, that there isn't any problem on STB side either. So problem must be at service. I create it like this:
public class UpdateService extends Service {
public UpdateService() {
HandlerThread thread = new HandlerThread("UpdateService:ServiceThread", THREAD_PRIORITY_MORE_FAVORABLE);
thread.start();
mServiceLooper = thread.getLooper();
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(mServiceLooper);
final Runnable updateRunnable = new Runnable() {
public void run() {
doStuff();
mHandler.postDelayed(this, UPDATE_CHECK_INTERVAL);
}
};
mHandler.post(updateRunnable);
}
private void doStuff() {
VersionService.getInstance().getVersionList(new VersionService.VersionListener() {
@Override
public void onSuccess(ArrayList<VersionObject> data) {
//code here is called for first 10 minutes
}
@Override
public void onFailure() {
//and here after 10 minutes
}
}
public void getVersionList(final VersionListener listener) {
try {
Call<VersionListApiResponse> call = ApiClient.getStbApi().getVersionList();
Response<VersionListApiResponse> response = call.execute();
if (response.isSuccessful())
{
VersionListApiResponse responseObject = response.body();
listener.onSuccess(responseObject.getVersionList());
}
}
catch (RuntimeException | IOException e)
{
listener.onFailure();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Server request looks like this:
public interface ApiStb {
@Headers({
"Accept:application/json",
"Accept-Charset:UTF-8",
"Content-type:application/json;charset=utf-8"
})
@GET("versionList")
Call<VersionListApiResponse> getVersionList();
}
Am I doing anything wrong? I have tried to change some things around. I used Retrofit both in sync and async. I have tried to downgrade retrofit and okhttp (didn't help). I tried to change return value in onStartCommand. I have overriden onDestroy() to check, if service is being killed (it isn't). I have tried to change postDelayed(delay) to some other value, but service stops after 10 minutes every time, doesn't matter if delay is 15 or 60 seconds. I have tried to restart service, when I get exception, like this:
stopService(new Intent(this, UpdateService.class));
startService(new Intent(this, UpdateService.class));
but I doesn't help. Only thing that helps is hard reboot of STB, nothing else. After reboot, it works fine for 10 minutes and then it starts throwing exceptions again. It's our own server and admins confirmed, that after 10 minutes, there were no new requests, so it seems that requests never leave device. DNS translation works fine (IP address in exception message is correct). I have tried to change connection timeout for network request, but even if I wait for 2 minutes, it still throws exception after that time.
After all of that, I have tried to install this service on another STB (different type/vendor) and there it works as expected. I would really appreciate, if someone could give me any advice. I suspected, that this device kills service for some reason, but onDestroy is never called. Could it be anything else?
Affected device is X96 Amlogic S905X Quad Core Android 6.0 TV Box (link: https://www.alibaba.com/product-detail/X96-Amlogic-S905X-Quad-Core-Android_60599604444.html?s=p )
Thank you.
EDIT: Possible duplicate/answer isn't related, I can catch connection timeout just fine and increasing connection timeout with:
client.setConnectTimeout(10, TimeUnit.MINUTES);
doesn't help.
However, I have some new info: I tried to add some other functionality to the service, that uses UDP and I run into same problem. Service works fine for 10 minutes, but then I keep getting:
java.net.SocketException: sendto failed: EPERM (Operation not permitted)
I suppose its somehow related? Any help would be really appreciated.
Solution for affected device (X96 Amlogic S905X Quad Core Android 6.0 TV Box) was to add at least one activity into Android Manifest. That activity is never shown to user, but somehow it fixes this problem.
(service is started from receiver with intent filter for android.intent.action.BOOT_COMPLETED)