如果没有互联网连接可用,则以 4 分钟的间隔将 AsyncTask 重新安排为接下来 20 分钟的 运行

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

我正在尝试在 SmsReceiver 广播上执行 AsyncTask。我的代码的问题是,如果在 SMS 广播接收器触发时没有可用的互联网连接,则 AsyncTask 不会执行。如果没有可用的互联网连接,我想在接下来的 20 分钟内以 4 分钟的间隔安排 AsyncTask 到 运行 5 次。如果在任何执行时 AsyncTask 从服务器获得响应,则取消下一次执行并更新 UI。我可以在 onPostExecute() 中更新 UI。我之前问过这个问题 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 但我不明白如何操纵我的代码来工作。如果有人可以帮助我让这段代码正常工作,我将不胜感激。

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);
}

}

编辑:1

更新了代码,但如果没有可用的互联网连接,SetAlarm 仍然不会被触发。我来自 PHP 背景。在 PHP 中,使用 cron 作业可以轻松设置重复任务。但这是我第一次写 Java 代码。到目前为止,AsyncTask 工作正常,但我真的不知道在哪里增加 count 做所有这些事情?

编辑:2

更新代码。

编辑:3

更新代码。它现在工作。

解决此问题的一种方法是在没有互联网可用时使用 PendingIntent 和 AlarmManager 重新安排。

类似这样的事情(您需要更新您的 flagAlarmSet 并在适当的地方计数):

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);
      }

   }
}

scheduling/canceling 闹钟:

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);
 }

参考:Alarm Manager Example

还有一点需要注意,如果您打算使用收到的消息,则需要以某种方式缓存消息以用于重新安排的 PendingIntent。

请参阅 getMessagesFromIntent() 文档:

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

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

编辑:在此处重新设置您的计数:

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

编辑 2:好的,我想我知道问题出在哪里了。您需要向意图添加一个操作,并在 onReceive().

中查找 "ActionRetry"

我刚刚测试了这个并且它有效。

看看下面更新的代码:

    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);
    }
}