我正在尝试在SmsReceiver Broadcast上执行 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 工作正常,但我真的不知道在哪里增加计数做所有这些事情?
编辑:2
更新了代码。
编辑:3
更新了代码。它现在正在工作。
答案 0 :(得分: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添加一个动作,并寻找&#34; ActionRetry&#34;在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);
}
}