Practical Way to Find Out If Sms Has Been Sent

Practical way to find out if SMS has been sent

Yes, It is possible to listen SMS ContentProvider by using ContentObserver

Here is my example for Outgoing SMS:

First register a ContetObserver with content://sms/

   public class Smssendservice extends Service{

@Override
public void onCreate() {
SmsContent content = new SmsContent(new Handler());
// REGISTER ContetObserver
this.getContentResolver().
registerContentObserver(Uri.parse("content://sms/"), true, SMSObserver);
}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub

return null;
}

SMSObserver.class

       public class SMSObserver extends ContentObserver {
private Handler m_handler = null;

public SMSObserver(SMSLogger handler){
super(handler);
m_handler = handler;
}

@Override
public void onChange(boolean selfChange) {
super.onChange(bSelfChange);
Uri uriSMSURI = Uri.parse("content://sms");

Cursor cur = this.getContentResolver().query(uriSMSURI, null, null,
null, null);
cur.moveToNext();

String protocol = cur.getString(cur.getColumnIndex("protocol"));

if(protocol == null) {
//the message is sent out just now
}
else {
//the message is received just now
}
}
}

}

How to get sms sent confirmation for each contact/person in android?

This is a very simple example to demonstrate the use of the send and delivery PendingIntents available for all of the SmsManager#send*() methods, and attaching data to those to easily differentiate the results in the Receiver.

Attaching that data is as simple as putting extras on the Intents backing the PendingIntents we pass to the send*() methods. The catch is that PendingIntents might not behave as one expects. To conserve resources, the system will only create new ones when it must. The get*() methods will only return a distinct PendingIntent if the Intent is different per the Intent#filterEquals() method, the request code is not currently in use for an equal Intent, or an appropriate flag is passed.

Different extras on an otherwise-same Intent with the same request code will not cause a new PendingIntent to be created. Depending on the flag passed in that case, those extras might be ignored, or overwrite those in a currently active PendingIntent, which can lead to incorrect results.

In our example, we're basically using the same Intent for each send, so we'll ensure a distinct PendingIntent for each by passing unique request codes. This simple example uses the size of a shrinking list for those codes, which will be unique in the context of a single run. The request code can ultimately be any arbitrary int, as long as you know it's unused at the time of request.

The system will want to cache these PendingIntents, should we need them again in the near future, so we'll also pass FLAG_ONE_SHOT to "clear them out" after use, and make sure we get the correct, current extras in subsequent runs.

public class SmsActivity extends Activity implements View.OnClickListener {
private static final String SMS_SENT_ACTION = "com.mycompany.myapp.SMS_SENT";
private static final String SMS_DELIVERED_ACTION = "com.mycompany.myapp.SMS_DELIVERED";
private static final String EXTRA_NUMBER = "number";
private static final String EXTRA_MESSAGE = "message";

// Initialize our sample numbers list.
private final List<String> numberList = new ArrayList<String>() {{{
add("111-111-1111");
add("222-222-2222");
add("333-333-3333");
}}};

// Initialize our sample message list.
private final List<String> messageList = new ArrayList<String>() {{{
add("Hello.");
add("Howdy.");
add("Hi.");
}}};

private SmsManager smsManager;
private IntentFilter intentFilter;
private BroadcastReceiver resultsReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);

findViewById(R.id.button_send).setOnClickListener(this);

smsManager = SmsManager.getDefault();
resultsReceiver = new SmsResultReceiver();

intentFilter = new IntentFilter(SMS_SENT_ACTION);
intentFilter.addAction(SMS_DELIVERED_ACTION);
}

@Override
protected void onResume() {
super.onResume();
registerReceiver(resultsReceiver, intentFilter);
}

@Override
protected void onPause() {
super.onPause();
unregisterReceiver(resultsReceiver);
}

public void onClick(View v) {
v.setEnabled(false);
sendNextMessage();
}

private void sendNextMessage() {
// We're going to remove numbers and messages from
// the lists as we send, so if the lists are empty, we're done.
if (numberList.size() == 0) {
return;
}

// The list size is a sufficiently unique request code,
// for the PendingIntent since it decrements for each send.
int requestCode = numberList.size();

String number = numberList.get(0);
String message = messageList.get(0);

// The Intents must be implicit for this example,
// as we're registering our Receiver dynamically.
Intent sentIntent = new Intent(SMS_SENT_ACTION);
Intent deliveredIntent = new Intent(SMS_DELIVERED_ACTION);

// We attach the recipient's number and message to
// the Intents for easy retrieval in the Receiver.
sentIntent.putExtra(EXTRA_NUMBER, number);
sentIntent.putExtra(EXTRA_MESSAGE, message);
deliveredIntent.putExtra(EXTRA_NUMBER, number);
deliveredIntent.putExtra(EXTRA_MESSAGE, message);

// Construct the PendingIntents for the results.
// FLAG_ONE_SHOT cancels the PendingIntent after use so we
// can safely reuse the request codes in subsequent runs.
PendingIntent sentPI = PendingIntent.getBroadcast(this,
requestCode,
sentIntent,
PendingIntent.FLAG_ONE_SHOT);

PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
requestCode,
deliveredIntent,
PendingIntent.FLAG_ONE_SHOT);

// Send our message.
smsManager.sendTextMessage(number, null, message, sentPI, deliveredPI);

// Remove the number and message we just sent to from the lists.
numberList.remove(0);
messageList.remove(0);
}

private class SmsResultReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// A simple result Toast text.
String result = null;

// Get the result action.
String action = intent.getAction();

// Retrieve the recipient's number and message.
String number = intent.getStringExtra(EXTRA_NUMBER);
String message = intent.getStringExtra(EXTRA_MESSAGE);

// This is the result for a send.
if (SMS_SENT_ACTION.equals(action)) {
int resultCode = getResultCode();
result = "Send result : " + translateSentResult(resultCode);

// The current send is complete. Send the next one.
sendNextMessage();
}
// This is the result for a delivery.
else if (SMS_DELIVERED_ACTION.equals(action)) {
SmsMessage sms = null;

// A delivery result comes from the service
// center as a simple SMS in a single PDU.
byte[] pdu = intent.getByteArrayExtra("pdu");
String format = intent.getStringExtra("format");

// Construct the SmsMessage from the PDU.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && format != null) {
sms = SmsMessage.createFromPdu(pdu, format);
}
else {
sms = SmsMessage.createFromPdu(pdu);
}

// getResultCode() is not reliable for delivery results.
// We need to get the status from the SmsMessage.
result = "Delivery result : " + translateDeliveryStatus(sms.getStatus());
}

result = number + ", " + message + "\n" + result;
Toast.makeText(context, result, Toast.LENGTH_SHORT).show();
}

String translateSentResult(int resultCode) {
switch (resultCode) {
case Activity.RESULT_OK:
return "Activity.RESULT_OK";
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
return "SmsManager.RESULT_ERROR_GENERIC_FAILURE";
case SmsManager.RESULT_ERROR_RADIO_OFF:
return "SmsManager.RESULT_ERROR_RADIO_OFF";
case SmsManager.RESULT_ERROR_NULL_PDU:
return "SmsManager.RESULT_ERROR_NULL_PDU";
case SmsManager.RESULT_ERROR_NO_SERVICE:
return "SmsManager.RESULT_ERROR_NO_SERVICE";
default:
return "Unknown error code";
}
}

String translateDeliveryStatus(int status) {
switch (status) {
case Telephony.Sms.STATUS_COMPLETE:
return "Sms.STATUS_COMPLETE";
case Telephony.Sms.STATUS_FAILED:
return "Sms.STATUS_FAILED";
case Telephony.Sms.STATUS_PENDING:
return "Sms.STATUS_PENDING";
case Telephony.Sms.STATUS_NONE:
return "Sms.STATUS_NONE";
default:
return "Unknown status code";
}
}
}
}

Notes:

  • Do make note of the method we're using to get the delivery status. The result code in the Receiver is not a reliable indicator. We must check the getStatus() return of the SmsMessage obtained from the PDU extra on the Intent to get the actual result.

  • Also be aware that not all carriers provide delivery results, in which case the delivery PendingIntents will never fire. Do not rely on a delivery result.

  • This example uses a "correct", albeit simple, method to sequentially send multiple messages, in that it waits until the current send is compete before proceeding to the next. For short lists, you might be able to get away with a loop firing all of the sends as quickly as it executes, but this can result in a generic failure if the system can't keep up.

  • As noted, this is a very simple example. It is not really suitable for production, as the dynamically registered Receiver is tied to the Activity's lifecycle. Ideally, you'd want to implement a static Receiver class, registered in the manifest, and use explicit Intents to target it. Using a Service to process the results is also recommended, and those results could be delivered to the UI through any number of mechanisms; e.g., LocalBroadcastManager, another event bus implementation, Intents, Notifications, etc.

Android, Detect which app is sending SMS?

So I found a workaround. During when an app is sending a short message, it is a foreground process. So I just got the list of foreground processes when my onSMSSent() got called and found the app that is sending SMS, at the top of the list.

Though this might not be a solid solution, but as @Ch4t4r said, it seems there is no solution to directly get the SMS sending app and the trick sounds good enough.

iOS: Detect SMS / Email Recipients

It's not possible. SMS messaging is a one-way data flow. You send the message and the network will try to send it on. There is no receipt mechanism.

When they introduced iMessage, that has a delivery receipt mechanism (although it isn't always 100% correct) and can also mark if it has been read (if the recipient has read receipt turned on). But that isn't available for you to access programatically.

So, the short answer to your question is

No.

Count sent SMS messages

Yoc can count SMS Sent by user or any other Appliction on device from listening SMS ContentProvider by using ContentObserver

for complete example how you can register ContentObserver for SMS ContentProvider see in this post my answer

How to know that a specfic incoming sms is a reply to a previous outgoing sms?

Twilio developer evangelist here.

There is no way to do this I’m afraid, the SMS protocol has no information about users replying to a specific message. SMS is chronological, you can test this by opening your phone’s SMS app and trying to reply to the second to last message you received from someone. In SMS there’s no way to do that.

The best thing you can do is consider the messages chronologically, and assume that the reply is in response to the last message you sent to that number from the number you sent it from.

I suspect your are interested in this because you need to send notifications and get responses to those notifications and you realised you might need to send more than one notification to a user at a time but still get their responses. The best way to get around this is to use different numbers to send the different notification messages from, then when they reply you can tell which notification they were replying to by the number they sent the message to.



Related Topics



Leave a reply



Submit