Amandeep Singh
Amandeep Singh

Reputation: 274

Reschedule AsyncTask to run for next 20 minutes at the interval of 4 minutes if no internet connection is available

I am trying to execute AsyncTask on SmsReceiver Broadcast. The problem with my code is that if no internet connection is available when SMS broadcast receiver triggers, the AsyncTask does not execute. If no internet connection is available I want to schedule AsyncTask to run 5 times at the interval of 4 minutes for the next 20 minutes. If at any execution AsyncTask get response from server then cancel next executions & update UI. I can update UI in onPostExecute(). I earlier asked this question here but could not get any code help. A lot of posts are available on ScheduledExecutorService to schedule AsyncTask to run at interval of x minutes, but I could not find any to post mentioning AsyncTask to run for x minutes at the interval of x minutes. Only on the official Android website a Beeper example is available but I could not understand how to manipulate my code to work. I will be obliged if someone can help me is getting this code work.

SmsReceiver.java

public class SmsReceiver extends BroadcastReceiver {

static boolean flagAlarmSet;
static int count;

public void onReceive(Context context, Intent intent) {
    final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
    String action = intent.getAction();
    if (action.equals(ACTION_SMS_RECEIVED) || action.equals("ActionRetry")) {

        Log.d("SmsReceiver Broadcast triggered", "OK");
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            Log.d("Internet is connected", "flagAlarmSet to: " + flagAlarmSet);

            //if (flagAlarmSet) { //Removed
            count = 0;
            flagAlarmSet = false;
            CancelAlarm(context);
            Log.d("Alarm cancelled", "Alarm");
            //} //Removed

            //start AsyncTask even if flag was not set, you could have internet the first time in
            try {
                Log.d("Executing TheTask()", "OK");
                new TheTask().execute("http://somedomain.tld/index.php?userId=12345678");
            } catch (Exception e) {
                Log.d("TheTask Execution Error", "FAIL");
                e.printStackTrace();
            }
        }

        if (networkInfo == null) {
            if (!flagAlarmSet){
                Log.d("Internet is NOT connected.", "Schedule Retry");
                flagAlarmSet = true;
                SetAlarm(context);
                Log.d("Alarm Set", "Alarm");
            }
            else{
                count++;
                if (count >= 5){
                    Log.d("Internet is NOT connected.", "Max Tries Reached, Cancel Alarm");
                    count = 0;
                    flagAlarmSet = false;
                    CancelAlarm(context);
                }
            }
        }
    }
}

class TheTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... arg0) {
        String text = null;
        try {

            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(arg0[0]);
            HttpResponse resp = httpclient.execute(httppost);
            HttpEntity ent = resp.getEntity();
            text = EntityUtils.toString(ent);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return text;
    }

    @Override
    protected void onPreExecute() {
        Log.d("Test onPreExecute.", "OK");
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        Log.d("Result from server", result);

    }
}


public void SetAlarm(Context context)
{
    AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(context, SmsReceiver.class);
    i.setAction("ActionRetry");
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 * 60 * 4, 1000 * 60 * 4, pi); // Millisec * Second * Minute
}


public void CancelAlarm(Context context)
{
    Intent intent = new Intent(context, SmsReceiver.class);
    intent.setAction("ActionRetry");
    PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(sender);
}

}

EDIT: 1

Updated the code, but still if no internet connection is available, SetAlarm is not being triggered. I am coming from PHP background. In PHP it is easy to set repeating tasks using cron jobs. But it is the first time when I am writing Java codes. Till now the AsyncTask is working perfectly, But I really don't have any idea where to increment count do all this stuff ?

Edit: 2

Updated Code.

Edit: 3

Updated code. Its working now.

Upvotes: 1

Views: 266

Answers (1)

Daniel Nugent
Daniel Nugent

Reputation: 43322

One approach to solve this would be to use a PendingIntent and AlarmManager to re-schedule if no internet is available.

Something like this (you will need to update your flagAlarmSet and count where appropriate):

if (networkInfo != null && networkInfo.isConnected()) {
    Log.d("Network is connected. Executing TheTask()", "OK");

    if (flagAlarmSet == true){
       flagAlarmSet = false;
       CancelAlarm(context);
    }

    new TheTask().execute("http://somedomain.tld/index.php?userId=12345678");

}

if (networkInfo == null) {
   Log.d("Network is NOT connected.", "FAIL");
   if (flagAlarmSet == false){
       Log.d("Network is NOT connected.", "Schedule Retry");
       flagAlarmSet = true;
       SetAlarm(context);
   }
   else{
      if (count > 5){
          Log.d("Network is NOT connected.", "Max Tries Reached, Cancel Alarm");
          flagAlarmSet = false;
          CancelAlarm(context);
      }

   }
}

And something like this for scheduling/canceling alarm:

public void SetAlarm(Context context)
 {
     AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
     Intent i = new Intent(context, SmsReceiver.class);
     PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
     am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 4, pi); // Millisec * Second * Minute
 }

 public void CancelAlarm(Context context)
 {
     Intent intent = new Intent(context, SmsReceiver.class);
     PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
     alarmManager.cancel(sender);
 }

Reference: Alarm Manager Example

One more thing to note, if you are planning on using the message received, you would need to cache the message somehow for use in the re-scheduled PendingIntent.

See getMessagesFromIntent() documentation:

https://developer.android.com/reference/android/provider/Telephony.Sms.Intents.html#getMessagesFromIntent(android.content.Intent)

Example: Sending and Receiving SMS and MMS in Android (pre Kit Kat Android 4.4)

Edit: re-set your count here:

         else{
            if (count >= 5){
                Log.d("Network is NOT connected.", "Max Tries Reached, Cancel Alarm");
                count = 0;
                flagAlarmSet = false;
                CancelAlarm(context);
            }

Edit 2: Ok, I think I see what the problem is. You will need to add an action to the intent, and look for "ActionRetry" in onReceive().

I just tested this and it works.

Take a look at the updated code below:

    public class SmsReceiver extends BroadcastReceiver {

    static boolean flagAlarmSet;
    static int count;

    public void onReceive(Context context, Intent intent) {
        final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
        String action = intent.getAction();
        if (action.equals(ACTION_SMS_RECEIVED) || action.equals("ActionRetry")) {

            Log.d("SmsReceiver Broadcast triggered", "OK");
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

            if (networkInfo != null && networkInfo.isConnected()) {
                Log.d("Network is connected. Executing TheTask()", "OK");
                Log.d("connected", "flagAlarmSet to: " + flagAlarmSet);

                //if (flagAlarmSet) { //Removed
                    count = 0;
                    flagAlarmSet = false;
                    CancelAlarm(context);
                    Log.d("Alarm cancelled", "Alarm");
                 //} //Removed

                 //start AsyncTask even if flag was not set, you could have internet the first time in  
                 try {
                        Log.d("SmsReceiver Broadcast triggered", "OK");
                        new TheTask().execute("http://somedomain.tld/index.php?userId=12345678");
                    } catch (Exception e) {
                        Log.d("TheTask Execution Error", "FAIL");
                        e.printStackTrace();
                    }

            }

            if (networkInfo == null) {

                Log.d("Network is NOT connected.", "FAIL");
                if (!flagAlarmSet){
                    Log.d("Network is NOT connected.", "Schedule Retry");
                    flagAlarmSet = true;
                    SetAlarm(context);
                    Log.d("Alarm Set", "Alarm");
                }
                else{
                    count++;
                    if (count >= 5){
                        Log.d("Network is NOT connected.", "Max Tries Reached, Cancel Alarm");
                        count = 0;
                        flagAlarmSet = false;
                        CancelAlarm(context);
                    }
                }
            }
        }
    }

    class TheTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... arg0) {
            String text = null;
            try {

                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(arg0[0]);
                HttpResponse resp = httpclient.execute(httppost);
                HttpEntity ent = resp.getEntity();
                text = EntityUtils.toString(ent);

            } catch (Exception e) {
                e.printStackTrace();
            }

            return text;
        }

        @Override
        protected void onPreExecute() {
            Log.d("Test onPreExecute.", "OK");
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            Log.d("Result from server", result);

        }
    }


    public void SetAlarm(Context context)
    {
        AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, SmsReceiver.class);
        i.setAction("ActionRetry");
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 * 60 * 4, 1000 * 60 * 4, pi); // Millisec * Second * Minute
    }


    public void CancelAlarm(Context context)
    {
        Intent intent = new Intent(context, SmsReceiver.class);
        intent.setAction("ActionRetry");
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(sender);
    }
}

Upvotes: 3

Related Questions