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

I want to send sms to multiple people and verify whether sms sent or not. I checked multiple links (mentioned here) and got the idea of using PendingIntent and broadCast Receiver for confirmation.
Practical way to find out if SMS has been sent
Sending text messages programmatically in android
http://mobiforge.com/design-development/sms-messaging-android
But the key problem is that, I have different 50 contacts number in an arrayList and their different msgs in another arrayList.
I use this code :
for (Condition) {
sms = SmsManager.getDefault();
try {
. . . sms.sendTextMessage(phoneNumbers[i], null, messages[i], sentPI, deliveredPI);
}
catch(IllegalArgumentException e) { }
}
Now, I can't identify how many people do get their msg and how many don't. Because as shown in post(mentioned link above), every time we just get one msg, "SMS delivered".
So please let me know, how can I put "extras" in Intent, when I send msg and get the extras from broadcast Receiver to get the detail of specific contact/person.
One More thing : There are four different option for flag value in PendingIntent
(FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT).
Which one should I use when I send messages in for loop for correct result?

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";
}
}
}
}
The translateSentResult() method is modified from a similar one in AOSP's old default SMS app. Licensed under the Apache License, Version 2.0.
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.

Related

Trouble Accurately Logging Several Back-to-Back SMS Delivery Intents for Android

I am developing an android app that rapidly sends multiple SMS messages almost simultaneously to the same number (Please note this is for research purposes). I need this app to also track it's delivery intent, which I do by adding a bundle containing the information I want the intent to carry. The problem I am running into, however, is as follows:
If I use no pending intent flag (aka 0) or FLAG_IMMUTABLE, the bundle value always remains the same as the first message sent and I get a dump of all the messages delivered.
If I use FLAG_UPDATE_CURRENT, I get a bundle value that updates sporadically/randomly (multiple intents contain the same bundle value), and I get a dump of all the messages delivered.
If I use FLAG_ONE_SHOT, I get the accurate bundle value assigned (the value as it is meant to be received) BUT I only get a dump of a very small amount of the intents, and that amount stays small(~1%) even if I happen to send over 1000 messages back-to-back.
Here is the portion of the message sending method responsible for sending the SMSs in MainActivity:
int z = 0;
for(int j=1; j<=messageCnt;j++){
try {
Intent dI = new Intent("SMS_DELIVERED");
Bundle b = new Bundle();
b.putString("MSGNUM",Integer.toString(z+1));
dI.putExtras(b);
dI.putExtra("MNUMSTR",Integer.toString(z+1));
PendingIntent deliveredIntent = PendingIntent.getBroadcast(getApplicationContext(),0,dI,PendingIntent.FLAG_ONE_SHOT);
deliveredPendingIntents.add(z,deliveredIntent);
SmsManager.getDefault().sendTextMessage(phoneNum, null, message[z], null, deliveredIntent);
b.clear();
}
catch (Exception e){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
crashTrack.add((Long.toString(System.currentTimeMillis())).concat(",").concat("'").concat(sw.toString()).concat("'\n"));
//reset all incremental value back one for proper repeat
j=j-1;
continue; //jump back to for loop and reattempt send.
}
}
Then, wherever I want (whether it be in a new app or in the current app), I put the following to register my receiver class.
//Create Broadcast receivers for sent and delivered intents
SmsDeliveredReceiver SDR = new SmsDeliveredReceiver();
//register the receivers
registerReceiver(SDR, new IntentFilter("SMS_DELIVERED"));
And finally, my broadcast reciever class for the intent, SmsDeliveredReciever:
public class SmsDeliveredReceiver extends BroadcastReceiver {
protected static int sentCount = 0;
#Override
public void onReceive(Context context, Intent dI){
/*File delivDumpName = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),MainActivity.dateTime.concat("DelivDump.txt"));
File delivfailDumpName = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),MainActivity.dateTime.concat("DelivFailDump.txt"));*/
Bundle bundle = dI.getExtras();
switch (getResultCode()){
case Activity.RESULT_OK:
if(bundle!=null){
String msgNum = bundle.getString("MSGNUM","0");
MainActivity.delvDump.add(Long.toString(System.currentTimeMillis()).concat(",'Msg ").concat(msgNum).concat("'\n"));
} else {
MainActivity.delvDump.add(Long.toString(System.currentTimeMillis()).concat(",'Msg ").concat("Number Unknown'\n"));//Integer.toString(sentCount)).concat("'\n"));
}
break;
case Activity.RESULT_CANCELED:
if(bundle!=null){
String msgNum = bundle.getString("MSGNUM","0");
MainActivity.delvDump.add(Long.toString(System.currentTimeMillis()).concat(",'Sms Failed to Deliver.',' Msg ").concat(msgNum).concat("'\n"));
} else {
MainActivity.delvDump.add(Long.toString(System.currentTimeMillis()).concat(",'Sms Failed to Deliver.',' Msg ").concat("Number Unknown'\n"));//Integer.toString(sentCount)).concat("'\n"));
}
break;
}
/*MainActivity.writeFiles(delivDumpName,String.valueOf(MainActivity.delvDump));
MainActivity.writeFiles(delivfailDumpName, String.valueOf(MainActivity.delvFailDump));*/
sentCount++;
}
}
Note that the exact same thing happens for the SendIntent. I've read all of the Google Android SDK Docs, and stackoverflow so far has provided answers that only work for alerts/alarms and not SMS intents, where the only existing tutorials and forum entries for SMS are single-send SMS. And no, I am not trying to send a multi-part message.
Desired output:
All SMS delivery intents should be captured in the broadcast receiver
Each intent captured must output its own unique message association number via the bundle.
The amount of intents captured should equal the number of messages successfully sent (yes, I do have a way to check whether the message got received or not)
Is this desired output even possible, or am I asking too much out of Android?
Whether the receiver is a separate app or not does not matter to me, though it is preferred if its a separate app.
Note: Everything in the app is functional and error-free except accurately tracking/logging the sent/delivered intents.

SmsManager: get message recipient phone number from BroadcastReceiver

There is how I send message to multiple recipient:
public void send(List<User> participants,
Func1<User, String> messageTextCallback,
Subscriber<SendingProgress> subscriber) { // TODO: throw error
Observable<SendingProgress> observable = Observable.create(sub -> {
String unequalSmsSentAction = UUID.randomUUID().toString();
context.registerReceiver(new BroadcastReceiver() {
private int totalToSend = participants.size();
private int sentCounter = 0;
#Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
sub.onNext(
new SendingProgress(totalToSend, ++sentCounter)
);
if(sentCounter == totalToSend) {
sub.onCompleted();
context.unregisterReceiver(this);
}
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:
subscriber.onError(new SendSmsException());
sub.onCompleted();
}
}
}, new IntentFilter(unequalSmsSentAction));
int totalToSend = participants.size();
for(int i = 0; i < totalToSend; i++) {
User participant = participants.get(i);
logger.d(TAG, "sending to: " + participant.getUsername());
PendingIntent sentPi = PendingIntent.getBroadcast(context, 0, new Intent(unequalSmsSentAction), 0);
smsManager.sendTextMessage(
participant.getPhones().get(0),
null,
messageTextCallback.call(participant),
sentPi,
null
);
}
});
observable
.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)
.subscribe(subscriber);
}
This code call SmsManager.sendTextMessage(...) for every User's phone number.
BroadcastReceiver receives every sent message and notifies subscriber about it. I want to get phone number of SMS recipient inside BroadcastReceiver.onReceive to pass it through SendingProgress.
Is there any way to do this?
Should I send multiple SMSes synchronously?
Is there any way to do this?
Step #1: Put the information that you want in an extra of your unequalSmsSentAction Intent
Step #2: Use a unique ID for each PendingIntent (the second parameter of your getBroadcast() call, where you have 0 -- replace it with a distinct value for each SMS)
Step #3: Read the information out of extra in the Intent delivered to your BroadcastReceiver
However, any app can listen for your unequalSmsSentAction broadcasts. Ideally, set the value of the extra in the Intent to be something you can use to find the phone number, but that cannot be used by any other app that receives those broadcasts.
Should I send multiple SMSes synchronously?
AFAIK, you cannot send them synchronously.

How can i create an Outbox capable of sending multiple SMS to same recipient?

I am in the middle of creating an App that will send multiple SMS messages to a single recipient - one every minute. These messages contain GPS coordinates as part of a tracking system that is attached to an object.
The object will be moving in and out of signal so messages may or may not be sent. I would like to store these messages and send them at a later date. This means I need to send a lot of SMS messages when the object is next in signal. HOWEVER. I run into trouble when I try to send the stored messages. Is there any way to identify what SMS message belongs to what BroadcastReceiver? Knowing this would allow me to save (for sending later) any message that was not sent and at the same time remove any messages that have already been sent.
IE the object travels out of signal. Every minute a GPS coordinate is retrieved. Message is not sent so it is stored in a vector. after 5 minutes object is back in signal with 5 messages to send. If halfway during the sending of these 5 messages the object loses signal I would and is only able to send 3 of the messages (no particular order) I would like to know which 3 were sent and which 2 were not.
Some code is below.
public class FixingmsgsActivity extends Activity {
private static final int MAX_SMS_MESSAGE_LENGTH = 160;
private static final String SMS_DELIVERED = "SMS_DELIVERED";
private static final String SMS_SENT = "SMS_SENT";
private String SendTo = "02102980174";
private String SendToFull = "+642102980174";
private Vector<String> testmsg = new Vector<String>();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
registerReceiver(sendreceiver, new IntentFilter(SMS_SENT));
registerReceiver(deliveredreceiver, new IntentFilter(SMS_DELIVERED));
// registerReceiver(smsreceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
testmsg.addElement("one");
testmsg.addElement("two");
testmsg.addElement("three");
testmsg.addElement("four");
testmsg.addElement("five");
testmsg.addElement("six");
testmsg.addElement("seven");
testmsg.addElement("eight");
testmsg.addElement("nine");
for(int i=0;i < testmsg.size();i++){
sendSms(SendTo,testmsg.elementAt(i));
}
}
private void sendSms(String phonenumber,String message){
SmsManager manager = SmsManager.getDefault();
Intent sendIntent = new Intent("SMS_SENT");
sendIntent.putExtra("message", message);
PendingIntent piSend = PendingIntent.getBroadcast(this, 0, sendIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent piDelivered = PendingIntent.getBroadcast(this, 0, new Intent(SMS_DELIVERED), 0);
int length = message.length();
if(length > MAX_SMS_MESSAGE_LENGTH)
{
ArrayList<String> messagelist = manager.divideMessage(message);
manager.sendMultipartTextMessage(phonenumber, null, messagelist, null, null);
}
else
{
//Toast.makeText(getBaseContext(), message, Toast.LENGTH_SHORT).show();
manager.sendTextMessage(phonenumber, null, message, piSend, piDelivered);
}
}
private BroadcastReceiver sendreceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
switch(getResultCode())
{
case Activity.RESULT_OK: //Message has been sent
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE: //message not sent. Which one? I would like to store this SMS so I can send it later.
break;
case SmsManager.RESULT_ERROR_NO_SERVICE: //message not sent. Which one?
break;
case SmsManager.RESULT_ERROR_NULL_PDU: //message not sent. Which one?
break;
case SmsManager.RESULT_ERROR_RADIO_OFF: //message not sent. Which one?
break;
}
}
};
private BroadcastReceiver deliveredreceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String info = "Delivery information: ";
switch(getResultCode())
{
case Activity.RESULT_OK: info += "delivered";
break;
case Activity.RESULT_CANCELED: info += "not delivered";
break;
}
}
};
}
I have tried using Intents with putExtra however this will only give the last SMS extra in the broadcastreceiver. For example in the above code the extra "message" in the onrecieve method would output "nine" "nine" "nine" "nine" "nine" "nine" "nine" "nine" "nine"
As I am sending multiple messages I would like that to be something like
"one" "two" etc. This wiould allow me to identify what message was not sent and what one was
Sorry for the long read. Thanks
Daniel H
I think I have it figured out now.
My error was in creating a for loop to send all the SMS messages though. This will create either multiple recievers or will result in a loss of information for the receiver as to what Onrecieve call belongs to what SMS.
What I did...
public void sendSms(){
//messagev = vector or arraylist of messages to be sent
//So that there are no over run errors.
//IE not sending blank messages
if (messagev.isEmpty()){
return;
}
SmsManager manager = SmsManager.getDefault();
//only send the last element in the array. This will allow the latest message to be sent
//due to adding messages to messagev being appended on the end.
String message = messagev.lastElement();
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,new Intent(SMS_SENT),0);
//register a new reciever for the sms to be sent.
registerReceiver(new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
arg0.unregisterReceiver(this); //remove reciever for this sms
messagev.removeElementAt(messagev.size()-1); //remove the element from the message array
if (!messagev.isEmpty()){ //if there are more messages to send then cann the sendSms function again.
sendSms();
}
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
arg0.unregisterReceiver(this);
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
arg0.unregisterReceiver(this);
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
arg0.unregisterReceiver(this);
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
arg0.unregisterReceiver(this);
break;
}
}
},new IntentFilter(SMS_SENT));
manager.sendTextMessage(SendTo, null, message, sentPI, null); //send the sms
}
This function when called will iterate (through something similar to recursion) through all the messages to be sent and if it is sent it will remove that SMS from the collection.
If the SMS is not sent then it unregisters the reciever and the SMS is not removed from the array of SMS and will try to be sent the next time that the sendSms method is called.
The method should have a default with unregister reciever in it so that if it all goes to pot the reciever is unregistered. Otherwise it seems to work fine.
Cheers - Daniel H

How to determine the phone number of a current caller in a stand-alone application

I'd like to build an Android application that can contact the current caller via a pre-determined text message. Sending a text message is simple enough but determining the phone number of the current caller in a stand-alone application is the challenge. Is the there an easy way to divine the phone number so I can send them a message while still on the call?
Of course there are manual ways to do this: write down the number, key it into a new text message, enter the message. But I want to define the message up front and be able to "send it to current caller".
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneCallStateListener customPhoneListener = new PhoneCallStateListener(context);
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
helper = new ContactDatabaseHelper(context);
list = helper.getAllContacts();
try{
incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (list.size() != 0){
for ( int i = 0, size = list.size(); i < size; i++ ){
if (PhoneNumberUtils.compare(incomingNumber, list.get(i).getContactNumber())){
ToastMsg.showToast(context,list.get(i).getContactName()+" Calling");
}
}
}
}catch (Exception e) {
// TODO: handle exception
}
}
public class PhoneCallStateListener extends PhoneStateListener{
private Context context;
public PhoneCallStateListener(Context context){
this.context = context;
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
break;
case PhoneStateListener.LISTEN_CALL_STATE:
}
super.onCallStateChanged(state, incomingNumber);
}
}
For your sistuation the best I can think of is to use PhoneStateListener. It contains onCallStateChanged handler. One of the arguments is a String containing the incoming phone number.
Source:
http://developer.android.com/reference/android/telephony/PhoneStateListener.html
Ctrl + F and type in "Incoming" and you will find everything you need to know.
EDIT: To make sure you're app starts on the startup of your phone, just add a BroadcastReciever. How to start an Application on startup?
Register a BroadcastReceiver in your manifest that listens to ACTION_PHONE_STATE_CHANGED.
Broadcast intent action indicating that the call state (cellular) on
the device has changed.
The EXTRA_STATE extra indicates the new call state. If the new state
is RINGING, a second extra EXTRA_INCOMING_NUMBER provides the incoming
phone number as a String.
Requires the READ_PHONE_STATE permission.
This was a sticky broadcast in version 1.0, but it is no longer
sticky. Instead, use getCallState() to synchronously query the current
call state.
This way you don't need the user to launch your app before receiving a call.

On Nexus ONE, getting RESULT_ERROR_GENERIC_FAILURE when trying to use SmsManager.sendTextMessage()

I've been successfully testing my app which sends a text message to another phone number. The problem came when I sent this to a buddy that has the Nexus One. I added a pending intent to sendTextMessage() and saw I'm hitting: RESULT_ERROR_GENERIC_FAILURE.
Generic Error is non specific error, sometimes it is shown if our
Network provider don't send sms on non existing numbers, I have found
this after research, I have 2 androids, both are from different
Providers, one provider sends Message on non existing phone numbers,
so I am not facing Generic Error Problem in this sim, on the other
hand the 2nd Network Provider Don't sends the message on non existing
phone number, so the generic error is appear in this Case. Guys kindly
check your Programs with other Networks, May be It solves your
Problem. thanks.
Mi problem is the same and how Jonathan Akers said, the RESULT_ERROR_GENERIC_FAILURE, is triggered by the sender mobile (Nexus One) to any other, so, nothing sms message is send use this mobile phone by programmatically mode without use intent sms messaging.
All works fine using two android emulators.
I use BroadcastReceiver for listen sms events like as:
public class ConfigSMS {
private static final String CLASS_NAME = "smsTestClass";
private static PendingIntent sentPI = null;
private static PendingIntent deliverPI = null;
//--------------- Getters & Setters --------------------------//
public static PendingIntent getSentPI() {
if (sentPI == null)
initPI();
return sentPI;
}
public static void setSentPI(PendingIntent sentPI) {
ConfigSMS.sentPI = sentPI;
}
public static PendingIntent getDeliverPI() {
if (deliverPI == null)
initPI();
return deliverPI;
}
public static void setDeliverPI(PendingIntent deliverPI) {
ConfigSMS.deliverPI = deliverPI;
}
//------------------------------------------------------------------------//
/**
* Initialize the Intents and BroadcastReceivers
*/
public static void initPI () {
monitoringSMS();
}
/**
* Create the inits and BroadcastReceivers for listen sms actions
*/
private static void monitoringSMS () {
try {
final String SENT_SMS_ACTION = "SENT_SMS_ACTION";
final String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";
//Create the setIntent parameter
Intent sentIntent = new Intent(SENT_SMS_ACTION);
sentPI = PendingIntent.getBroadcast(
ConfigAppValues.getContext(),
0,
sentIntent,
0);
//Create the deliveryIntetn parameter
Intent deliveryIntent = new Intent(DELIVERED_SMS_ACTION);
deliverPI = PendingIntent.getBroadcast(
ConfigAppValues.getContext(),
0,
deliveryIntent,
0);
//Register the Broadcast Receivers
ConfigAppValues.getContext().registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Log.d(CLASS_NAME, "Successful transmission!!");
showNotificationToast("Successful transmission!!");
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Log.d(CLASS_NAME, "Nonspecific Failure!!");
showNotificationToast("Nonspecific Failure!!");
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Log.d(CLASS_NAME, "Radio is turned Off!!");
showNotificationToast("Nonspecific Failure!!");
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Log.d(CLASS_NAME, "PDU Failure");
showNotificationToast("PDU Failure");
break;
}
}
}, new IntentFilter(SENT_SMS_ACTION));
ConfigAppValues.getContext().registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d(CLASS_NAME, "The user have been receive the SMS message!!");
}
}, new IntentFilter(DELIVERED_SMS_ACTION));
}catch (Exception e) {
Log.e(CLASS_NAME, ExceptionUtils.exceptionTraceToString(
e.toString(),
e.getStackTrace()));
}
}
private static void showNotificationToast (String message) {
try {
//Show the toast message
Toast.makeText(
ConfigAppValues.getContext(),
message,
Toast.LENGTH_SHORT).show();
}catch (Exception e) {
Log.e(CLASS_NAME, ExceptionUtils.exceptionTraceToString(e.toString(), e.getStackTrace()));
}
}
}
`
And for send sms message i use this PendingInents how has been put at the application launch, my logs said that all was right except for this, that launch the RESULT_ERROR_GENERIC_FAILURE flag.
The code is:
SmsManager smsManager = SmsManager.getDefault();
Log.d(CLASS_NAME, "SmsText: " + smsText);
//String test = "5556";
smsManager.sendTextMessage(
receiver,
null,
smsText,
ConfigSMS.getSentPI(),
ConfigSMS.getDeliverPI());
And that is all i don't have idea that is for my mobile phone or anything, how i said all works fine using two android emulators, Activity.RESULT_OK is launched and the sms message is received for the listen emulator.
Thanks for all!!

Categories

Resources