Reputation: 274
I am trying to execute AsyncTask on SmsReceiver Broadcast. The problem with my code is that if no internet connection is available when SMS broadcast receiver triggers, the AsyncTask does not execute. If no internet connection is available I want to schedule AsyncTask to run 5 times at the interval of 4 minutes for the next 20 minutes. If at any execution AsyncTask get response from server then cancel next executions & update UI. I can update UI in onPostExecute(). I earlier asked this question 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 but I could not understand how to manipulate my code to work. I will be obliged if someone can help me is getting this code work.
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);
}
}
EDIT: 1
Updated the code, but still if no internet connection is available, SetAlarm is not being triggered. I am coming from PHP background. In PHP it is easy to set repeating tasks using cron jobs. But it is the first time when I am writing Java codes. Till now the AsyncTask is working perfectly, But I really don't have any idea where to increment count do all this stuff ?
Edit: 2
Updated Code.
Edit: 3
Updated code. Its working now.
Upvotes: 1
Views: 266
Reputation: 43322
One approach to solve this would be to use a PendingIntent and AlarmManager to re-schedule if no internet is available.
Something like this (you will need to update your flagAlarmSet and count where appropriate):
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);
}
}
}
And something like this for scheduling/canceling alarm:
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);
}
Reference: Alarm Manager Example
One more thing to note, if you are planning on using the message received, you would need to cache the message somehow for use in the re-scheduled PendingIntent.
See getMessagesFromIntent()
documentation:
Example: Sending and Receiving SMS and MMS in Android (pre Kit Kat Android 4.4)
Edit: re-set your count here:
else{
if (count >= 5){
Log.d("Network is NOT connected.", "Max Tries Reached, Cancel Alarm");
count = 0;
flagAlarmSet = false;
CancelAlarm(context);
}
Edit 2: Ok, I think I see what the problem is. You will need to add an action to the intent, and look for "ActionRetry" in onReceive()
.
I just tested this and it works.
Take a look at the updated code below:
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);
}
}
Upvotes: 3