I have a POST message I absolutely have to send on Android in a given circumstance, to the point I would like it to keep trying until it completes. I was under the understanding that setting:
urlConnection.setConnectTimeout(0);
would keep trying the connection until it goes through, but what is actually happening is the try block is failing, and the UnknownHostException is being thrown instead:
private class SendAlert extends AsyncTask<String, String, String> {
protected String doInBackground(String... strings) {
Log.d(TAG, "sendAlarm: sending alarm");
String stringUrl = createUri();
HttpsURLConnection urlConnection = null;
BufferedReader reader = null;
String postData = "";
Log.d(TAG, "sendAlarm: apikey: " + apiKey);
try{
Log.d(TAG, "sendAlarm: trying");
URL finalURL = new URL(stringUrl);
urlConnection = (HttpsURLConnection)finalURL.openConnection();
urlConnection.setReadTimeout(10000);
urlConnection.setConnectTimeout(0);
urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
urlConnection.setRequestProperty("Accept","application/json");
urlConnection.setRequestProperty("x-api-key",apiKey);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "doInBackground: response code = " + responseCode);
}catch (MalformedURLException e) {
e.printStackTrace();
Log.d(TAG, "doInBackground: error 1 " + e.toString());
}catch(UnknownHostException e){
Log.d(TAG, "doInBackground: e: " + e);
Log.d(TAG, "doInBackground: retrying");
}
catch(Exception e){
Log.d(TAG, "doInBackground: error 2 " + e.toString());
}
Wondering what the best way to set up the post message on Android is, to keep trying the connection until it goes through, even if the phone is on airplane mode for 5 hours.
Edit: going of @user3252344's answer below, is there any problem with calling the function again directly in the catch block of the AyncTask:
catch(UnknownHostException e){
Log.d(TAG, "doInBackground: e: " + e);
Log.d(TAG, "doInBackground: retrying");
SendAlarm sendAlarm = new SendAlarm;
sendAlarm.execute();
}
Setting the connection timeout to 0 will mean it won't timeout, but if it fails to connect it won't handle it still. I'm guessing you get a an UnknownHostException
because it fails to resolve the url since it can't reach a DNS server.
I'd suggest you just set a reasonable connection timeout, catch the timeout exception if it happens and re-run.
final int READ_TIMEOUT = 500; // Timeout
final int RETRY_MS = 2000; //Retry every 2 seconds
final Handler handler = new Handler();
Runnable myUrlCall = () -> {
try {
//Make things
urlConnect.setReadTimeout(READ_TIMEOUT);
//Make the URL call, do response
} catch (SocketTimeoutException e) {
handler.postDelayed(myUrlCall, RETRY_MS);
} catch (/* other unintended errors*/ e) {
//Log the error or alert the user
}
};
handler.post(myUrlCall);
Possible even better idea: use Android settings to check if there's internet before you make the call. If there's no internet, use a longer delay. Something like this would be the code you're looking for.