Note that there are some explanatory texts on larger screens.

plurals
  1. POSend SMS until it is successful
    text
    copied!<p>I am trying to send an urgent SMS from my application. I have to make sure that the SMS is being sent successfully.</p> <p>The SMS is being sent after the boot of the Android system and after a check is being made.</p> <p>So I have a service class that handles the BOOT_COMPLETED intent-filter. This class makes a check and if something is true then it tries to send an SMS message via another class that "extends Service"</p> <p>After it makes sure that the sms is successfully sent, both services (the one that handles the boot call and the one that sends the sms) must exit.</p> <p><strong>Question 1</strong>: How to make my sms sending function be called with a timeout without getting the application being unresponsive message? Currently I am using this (I don't know if it is the correct way to do it, though it works):</p> <pre><code>Timer mTimer = new Timer(); //wait a small timeout prior to sending the message. mTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { this.cancel(); //I don't want to run the timer more than once sms_sender sms = new sms_sender(); sms.sendSMS(phoneNumber, messageText); } }, 30000, 30000); //run sendSMS() after 30 seconds </code></pre> <p><strong>Question 2</strong>: How to implement the sendSMS function so as to retry every 30 seconds after realizing that the last attempt was a fail?</p> <p><strong>Question 3</strong>: How to stop both services after I realize that the SMS was successfully sent?</p> <p>This is my code which does not work:</p> <pre><code>public class sms_sender extends Service { @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } final String SENT = "SMS_SENT"; public void sendSMS(final String phoneNumber, final String message, final boolean check_result) { PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0); registerReceiver(new BroadcastReceiver(){ @Override public void onReceive(Context arg0, Intent arg1) { if(!check_result) return; switch (getResultCode()) { case Activity.RESULT_OK: //exit stopSelf(); return; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: case SmsManager.RESULT_ERROR_NO_SERVICE: case SmsManager.RESULT_ERROR_NULL_PDU: case SmsManager.RESULT_ERROR_RADIO_OFF: //try again in 1 minute Timer mTimer = new Timer(); mTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { this.cancel(); //no need to run again, if it fails, this exact code will run again sendSMS(phoneNumber, message, true); } }, 60000, 60000); return; } } }, new IntentFilter(SENT)); SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(phoneNumber, null, message, sentPI, null); } } </code></pre> <p>Currently the program crashes on the PendingIntent call. I tried to implement the BroadCastReceiver on the onCreate method using private member variables so as to call the sendSMS() function again through the onReceive method, but the onReceive never seemed to run.</p> <p>-- EDIT --</p> <p>So, this is my final working code. I guess that my case is special because it doesn't work on a UI thread. I have a Broadcast Receiver that runs on Boot. I am trying to send an SMS message until it is successfully sent.</p> <p>This Boot Broadcast Receiver starts a service. This is some code from it:</p> <pre><code>public class service extends Service{ static public service serv; //member variable. Initializing to null so as to know whether to unregister the service or not private BroadcastReceiver messageSent = null; ... ... @Override public void onStart(Intent intent, int startid) { serv=this; //will use this static variable in order to shutdown the service when the message is successfully sent ... ... if(somethingIsTrue()){ //register receiver messageSent = new sent_message(); registerReceiver(messageSent, new IntentFilter(sms_sender.INTENT_MESSAGE_SENT)); startMessageServiceIntent(messageText, phoneNumber); //function code can be found on accepted answer } } } </code></pre> <p>The sent_message class is the following:</p> <pre><code>public class sent_message extends BroadcastReceiver { private Context pubCon; private void startMessageServiceIntent(String message, String receiver) { Intent i = new Intent(pubCon, sms_sender.class); i.putExtra(sms_sender.EXTRA_MESSAGE, message); i.putExtra(sms_sender.EXTRA_RECEIVERS, new String[] { receiver }); pubCon.startService(i); } @Override public void onReceive(Context context, Intent intent) { pubCon=context; switch (getResultCode()) { case Activity.RESULT_OK: //all went OK, stop the service where this is called from service.serv.stopSelf(); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: case SmsManager.RESULT_ERROR_NO_SERVICE: case SmsManager.RESULT_ERROR_NULL_PDU: case SmsManager.RESULT_ERROR_RADIO_OFF: //try sending the message again after 30s new Handler().postDelayed(new Runnable(){ @Override public void run(){ startMessageServiceIntent(service.messageText, service.phoneNumber); } }, 30000); break; } } } </code></pre> <p>And a simplified (accepts only one receiver) version of the sms_sender class is the following:</p> <pre><code>public class sms_sender extends IntentService { public static final String INTENT_MESSAGE_SENT = "message.sent"; public static final String INTENT_MESSAGE_DELIVERED = "message.delivered"; public static final String EXTRA_MESSAGE = "extra.message"; public static final String EXTRA_RECEIVERS = "extra.receivers"; public sms_sender() { super("sms_sender"); } private static class IDGenerator { private static final AtomicInteger counter = new AtomicInteger(); public static int nextValue() { return counter.getAndIncrement(); } } public void sendSMS(String message, String receiver) { SmsManager sm = SmsManager.getDefault(); PendingIntent sentPI = null; Intent sentIntent = new Intent(INTENT_MESSAGE_SENT); int sentID = IDGenerator.nextValue(); sentPI = PendingIntent.getBroadcast(sms_sender.this, sentID, sentIntent, PendingIntent.FLAG_CANCEL_CURRENT); try { sm.sendTextMessage(receiver, null, message, sentPI, null); } catch (IllegalArgumentException e) { System.out.println("Illegal argument"); } } protected void onHandleIntent(Intent intent) { String message = intent.getStringExtra(EXTRA_MESSAGE); String[] receivers = intent.getStringArrayExtra(EXTRA_RECEIVERS); sendSMS(message, receivers[0]); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload