如果没有互联网连接可用,则以 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()
文档:
示例:
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);
}
}
我正在尝试在 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()
文档:
示例: 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()
.
我刚刚测试了这个并且它有效。
看看下面更新的代码:
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);
}
}