我正在尝试在 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);
}
还有一点需要注意,如果您计划使用收到的消息,则需要以某种方式缓存消息以用于重新安排的 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:好的,我想我知道问题出在哪里了。您需要向 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/