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

标签 java android android-asynctask

我正在尝试在 SmsReceiver 广播上执行 AsyncTask。我的代码的问题是,如果在 SMS 广播接收器触发时没有可用的互联网连接,则 AsyncTask 不会执行。如果没有可用的互联网连接,我想安排 AsyncTask 在接下来的 20 分钟内以 4 分钟的间隔运行 5 次。如果在任何执行时 AsyncTask 从服务器获得响应,则取消下一次执行并更新 UI。我可以在 onPostExecute() 中更新 UI。我早些时候问过这个问题 here 但无法获得任何代码帮助。 ScheduledExecutorService 上有很多帖子可以安排 AsyncTask 以 x 分钟的间隔运行,但我找不到任何帖子提到 AsyncTask 以 x 分钟的间隔运行 x 分钟。只有官方 Android 网站上有 Beeper example 可用,但我无法理解如何操作我的代码来工作。如果有人可以帮助我让这段代码正常工作,我将不胜感激。

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

   }
}

还有类似这样的用于安排/取消警报的东西:

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:好的,我想我知道问题出在哪里了。您需要向 Intent 添加一个操作,并在 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);
    }
}

关于java - 如果没有可用的互联网连接,则重新安排 AsyncTask 以 4 分钟为间隔在接下来的 20 分钟内运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29051975/

相关文章:

java - 替换字符串中的字符

java - 将电话号码或 CONTACT_ID 从 Android 联系方式传递到 Activity (类似 Whatsapp)

android - 带有完成操作按钮的多行 EditText

android - 使用 Amazon Lambda 通过 SNS 通知用户 DynamoDB 中的更改

android - AWD键盘的设置

java - Android:asyncTask 响应中的方法调用

java - Firebase Firestore 读取 Java 中的嵌套对象值 (Android)

java - 如何使用 AsyncTask 读取 HTTP 响应?

android - 如何在AsyncTask中设置ImageView

Java:RoundingMode 错误 - 找不到符号