Android C#: sending SMS from Android service - android

I have android service written using Xamarin Studio and I'm trying to send sms message from this service automatically. For sending I use the following code:
SmsManager.Default.SendTextMessage("+7926736XXXX", null, "Simple Service sent you a message", null, null);
As a result SMS didn't sent to other mobile but left in SMS list marked by red triangle. I can send them later by hands without any problem. Can anybody know where may be my error?

Try this,
SmsManager sms = SmsManager.getDefault();
PendingIntent sentPI;
String SENT = "SMS_SENT";
sentPI = PendingIntent.getBroadcast(this, 0,new Intent(SENT), 0);
sms.sendTextMessage("+7926736XXXX", null, message, sentPI, null);
OR
send it in intent like this
var smsUri = Android.Net.Uri.Parse("smsto:7926736XXXX");
var smsIntent = new Intent (Intent.ActionSendto, smsUri);
smsIntent.PutExtra ("sms_body", "Hello from Xamarin.Android");
StartActivity (smsIntent);
hope this will help.

Try checking the SmsResultError and SmsStatus of the sent and delivered intents to determine why your SMS is not working.
Add BroadcastReceiver inner class to your Service:
public YourSMSService : Service
{
const string SentAction = "SentAction";
const string DeliveredAction = "DeliveredAction";
SmsReceiver smsReceiver;
~~~~
class SmsReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == SentAction)
{
// `Log` it if needed...
Toast.MakeText(context, $"{(SmsResultError)ResultCode}", ToastLength.Long).Show();
}
if (intent.Action == DeliveredAction)
{
// `Log` it if needed...
Toast.MakeText(context, $"{(SmsStatus)ResultCode}", ToastLength.Long).Show();
}
}
}
~~~~
}
Create/Register the BroadcastReceiver (usually done in the Service .actor)
smsReceiver = new SmsReceiver();
RegisterReceiver(smsReceiver, new IntentFilter(SentAction));
RegisterReceiver(smsReceiver, new IntentFilter(DeliveredAction));
Supply sent and delivered PendingIntents to the SendTextMessage:
var sentIntent = PendingIntent.GetBroadcast(this, 0, new Intent(SentAction), 0);
var deliveredIntent = PendingIntent.GetBroadcast(this, 0, new Intent(DeliveredAction), 0);
SmsManager.Default.SendTextMessage("1234567890", null, "Simple Service sent you a message", sentIntent, deliveredIntent);
Now when you send an SMS in your service, you will get a Toast message of the status.

The question is closed. This is the hardware problem of the my phone. I connected my 10 yeas old chinese Samsung Galaxy copy and my application immediately started to work

Related

Android SendMultipartTextMessage with pendingIntents with Extra values same for all parts

I am successfully sending multi-part (concatenated) messages through android using Xamarin Studio and the SMS.Telephony.SmsManager Android library.
To send a message I am doing the following:
var longMessage = "This is a cØncatenated message sent to you through an android. This should appear as a single message. Hopefully it's as easy as that. It even has a function to break the message up. It probably took me longer to install Xamarin then it did to write the code and send the actual message";
var smsMgr = Android.Telephony.SmsManager.Default;
System.Collections.Generic.IList<string> parts = smsMgr.DivideMessage(longMessage);
IList<PendingIntent> pendingIntents = new List<PendingIntent>(parts.Count);
for (int i = 0; i < parts.Count; i++)
{
var intent = new Intent(DeliveryIntentAction);
intent.PutExtra("MessagePartText", parts[i]);
intent.PutExtra("MessagePartId", i.ToString());
PendingIntent pi = PendingIntent.GetBroadcast(this, 0, intent, 0);
pendingIntents.Add(pi);
}
smsMgr.SendMultipartTextMessage("17057178131",null, parts, pendingIntents, null);
I then have a receiver for the pending Intents that looks like this:
[BroadcastReceiver(Enabled = true)] //(Exported = true, Permission = "//receiver/#android:android.permission.SEND_SMS")]
[IntentFilter(new[] { DeliveryIntentAction }, Priority = int.MaxValue)]
public class SMSSentReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.GetStringExtra ("MessagePartId") != null)
lbl.Text += " Sent Response " + intent.GetStringExtra ("MessagePartId") + System.Environment.NewLine;
...
However, each time OnRecieve is called, intent.GetStringExtra("MessagePartId") has a value of "0" and the MessagePartText is the first part, not the part number/text that belongs to the message part sent.
Can anyone see why this may be the case?
Thank you
Using
PendingIntent pi = PendingIntent.GetBroadcast(this, 0, intent, 0);
attempts to override the existing pendingIntent.
To create a NEW intent and have it waiting, I had to change the requestCode parameter of GetBroadcast.
PendingIntent pi = PendingIntent.GetBroadcast(this, i, intent, 0);
Thanks

Trying to ID the SMS delivery confirmation

I am currently trying to get the confirmation for each sended SMS. I need to be sure that my SMS are send, so I used a BroadCastReceived to get the information :
Intent sentIntent = new Intent(SMS_SEND);
sentIntent.putExtra("key", idSms);
PendingIntent sentPI = PendingIntent.getBroadcast(getApplicationContext(), 0, sentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
SmsManager manager = SmsManager.getDefault();
try{
manager.sendTextMessage(exp, null, sms, sentPI, null);
put("sending " + sms); //Just a method to print in a textview use has a console
} catch (IllegalArgumentException e){
put("Exception " + e.getMessage());
}
and use a broadcast receiver like this
public void onReceive(Context context, Intent intent){
String idsms = intent.getExtras().getString("key");
switch (getResultCode()) {
case Activity.RESULT_OK:
put("ACK : #" + idsms);
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
case SmsManager.RESULT_ERROR_RADIO_OFF:
case SmsManager.RESULT_ERROR_NULL_PDU:
case SmsManager.RESULT_ERROR_NO_SERVICE:
put("BOOM " + getResultCode() + "\n\tfrom sms #" + idsms);
break;
}
}
This work like a charm until I try to send multiple messages at the same time, the extra receive is always from the last SMS send, so I can't ID which text are send and which are not.
Here is a simple example of what will happen.
When I use a loop to send 3sms:
id : 1, message : SMS 1
id : 2, message : SMS 2
id : 3, message : SMS 3
And the received will get:
ACK : #3
ACK : #3
ACK : #3
I understand that this come from the PendingIntent.FLAG_UPDATE_CURRENT but I can't find a solution. Anyone can explain to me how I should use the PendingIntent.getBroadcast(..) to be able to manage this or at least to put me on the right track.
Your problem is due the fact that PendingIntents can be reused by the system, if certain things about the requests are not different. In your code, you're passing FLAG_UPDATE_CURRENT, which is causing the stored Intent and its extras to be updated each time a PendingIntent is requested. This is why you're getting id : 3 for each of the messages. To correct this, you can call getBroadcast() with a unique request code (the second parameter) each time, which will create a new PendingIntent for each request, each with a separate Intent with their own extras.
In your case, the fix should be simple, assuming that idSms is unique for each message.
PendingIntent sentPI = PendingIntent.getBroadcast(getApplicationContext(),
Integer.parseInt(idSms),
sentIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

Sent SMS message is automatically written to the content provider while it shouldn't in Cyanogenmod KitKat

From android KitKat when my application is set as the default one, sent sms messages should not be written to the content provider by system:
Note: Beginning with Android 4.4 (API level 19), if and only if an app is not selected as the default SMS app, the system automatically writes messages sent using this method to the SMS Provider (the default SMS app is always responsible for writing its sent messages to the SMS Provider). For information about how to behave as the default SMS app, see Telephony.
But every message I send is automatically written without my interaction (I just call sendTextMessage() and it's taken care of)
May it be a bug in CyanogenMod or I am missing something?
Here is my Code:
#SuppressLint("NewApi")
public static void sendMessage(String messageBody, String phoneNumber,
Context context) {
if (messageBody.length() > 0 && phoneNumber.length() > 0) {
SmsManager sms = SmsManager.getDefault();
ArrayList<String> parts = sms.divideMessage(messageBody);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
if (prefs.getBoolean(SettingsActivity.KEY_SPLIT, false)) {
for (String singlePart : parts) {
sms.sendTextMessage(phoneNumber, null, singlePart, null,
null);
}
} else {
sms.sendMultipartTextMessage(phoneNumber, null, parts, null,
null);
}
}
/**
* Add message to content provider (after KitKat)
*/
// if (android.os.Build.VERSION.SDK_INT >=
// android.os.Build.VERSION_CODES.KITKAT) {
// Log.d(null, "adding sms to content provider");
// ContentValues values = new ContentValues();
// values.put(Telephony.Sms.ADDRESS, phoneNumber);
// values.put(Telephony.Sms.BODY, messageBody);
// // values.put(Telephony.Sms.READ, 0);
// values.put(Telephony.Sms.DATE, System.currentTimeMillis());
// // values.put(Telephony.Sms._ID,
// // msgs[i].getIndexOnIcc());
// context.getContentResolver().insert(Telephony.Sms.Sent.CONTENT_URI,
// values);
// }
}
I don't know why, but when I added sent and delivered pending intent new sms is not automatically added to content provider. This solved my problem
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
new Intent(SENT), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
new Intent(DELIVERED), 0);
sms.sendTextMessage(phoneNo, null, singlePart, sentPI, deliveredPI);
Code from this question: Trouble with sendMultipartText in android
I noticed the same bug in my app on two devices. All with custom roms (CM based).
Try to use this library android smsmms sending library and if the issue persists, it may mean that there is something wrong with your manifest file.

SmsManager.Default.SendTextMessage sends too many sms-xamarin

I have an app which is an activity and a broadcast receiver which is have registered it in the manifest and the activity is destroyed at some point.
What does this broadcast receiver do is that it listens to incoming SMS and if the sender is the same as a number (which the user specifies in the activity) it sends an empty SMS to that number (both numbers are the same). I have compiled it with Android 2.3 but there are 2 problems.
1 - The application sends too many messages to that number after receiving one message.
2 - The abortbroadcast() is not working.
This is my broadcast receiver:
namespace SmsBroadcastReceiver
{
[BroadcastReceiver]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED" }, Priority = Int32.MaxValue)]
public class SmsReceiver : BroadcastReceiver
{
public override void OnReceive (Context context, Intent intent)
{
ISharedPreferences pref = PreferenceManager.GetDefaultSharedPreferences (context);
string number = pref.GetString ("Number", "0");
Bundle b= intent.Extras;
var pdus = b.Get("pdus");
var castedPdus = JNIEnv.GetArray<Java.Lang.Object>(pdus.Handle);
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[0].Handle)];
JNIEnv.CopyArray(castedPdus[0].Handle, bytes);
SmsMessage msg= SmsMessage.CreateFromPdu (bytes);
if (msg.OriginatingAddress == number) {
//send empty sms
SmsManager.Default.SendTextMessage (msg.OriginatingAddress, null, "Empty", null, null);
InvokeAbortBroadcast ();
}
}
}
}
Remove
SmsManager.Default.SendTextMessage (msg.OriginatingAddress, null,"Empty", null, null);
this should fix your problem.
if (msg.OriginatingAddress == number) {
//send empty sms
//Remove /Comment below statement from your code.`enter code here`
SmsManager.Default.SendTextMessage (msg.OriginatingAddress, null, "Empty", null, null);
InvokeAbortBroadcast ();
}

Can i automatically send SMS (Without the user need to approve)

I'm rather new to Android.
Im trying to send SMS from Android application.
When using the SMS Intent the SMS window opens and the user needs to approve the SMS and send it.
Is there a way to automatically send the SMS without the user confirming it?
Thanks,
Lior
You can use this method to send an sms. If the sms is greater than 160 character then sendMultipartTextMessage is used.
private void sendSms(String phonenumber,String message, boolean isBinary)
{
SmsManager manager = SmsManager.getDefault();
PendingIntent piSend = PendingIntent.getBroadcast(this, 0, new Intent(SMS_SENT), 0);
PendingIntent piDelivered = PendingIntent.getBroadcast(this, 0, new Intent(SMS_DELIVERED), 0);
if(isBinary)
{
byte[] data = new byte[message.length()];
for(int index=0; index<message.length() && index < MAX_SMS_MESSAGE_LENGTH; ++index)
{
data[index] = (byte)message.charAt(index);
}
manager.sendDataMessage(phonenumber, null, (short) SMS_PORT, data,piSend, piDelivered);
}
else
{
int length = message.length();
if(length > MAX_SMS_MESSAGE_LENGTH)
{
ArrayList<String> messagelist = manager.divideMessage(message);
manager.sendMultipartTextMessage(phonenumber, null, messagelist, null, null);
}
else
{
manager.sendTextMessage(phonenumber, null, message, piSend, piDelivered);
}
}
}
Update
piSend and piDelivered are Pending Intent They can trigger a broadcast when the method finish sending an SMS
Here is sample code for broadcast receiver
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = null;
switch (getResultCode()) {
case Activity.RESULT_OK:
message = "Message sent!";
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
message = "Error. Message not sent.";
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
message = "Error: No service.";
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
message = "Error: Null PDU.";
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
message = "Error: Radio off.";
break;
}
AppMsg.makeText(SendMessagesWindow.this, message,
AppMsg.STYLE_CONFIRM).setLayoutGravity(Gravity.BOTTOM)
.show();
}
};
and you can register it using below line in your Activity
registerReceiver(receiver, new IntentFilter(SMS_SENT)); // SMS_SENT is a constant
Also don't forget to unregister broadcast in onDestroy
#Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
If your application has in the AndroidManifest.xml the following permission
<uses-permission android:name="android.permission.SEND_SMS"/>
you can send as many SMS as you want with
SmsManager manager = SmsManager.getDefault();
manager.sendTextMessage(...);
and that is all.
Yes, you can send SMS using the SmsManager. Please keep in mind that your application will need the SEND_SMS permission for this to work.
Yes, you can send sms without making user interaction...But it works, when user wants to send sms only to a single number.
try {
SmsManager.getDefault().sendTextMessage(RecipientNumber, null,
"Hello SMS!", null, null);
} catch (Exception e) {
AlertDialog.Builder alertDialogBuilder = new
AlertDialog.Builder(this);
AlertDialog dialog = alertDialogBuilder.create();
dialog.setMessage(e.getMessage());
dialog.show();
}
Also, add manifest permission....
<uses-permission android:name="android.permission.SEND_SMS"/>

Categories

Resources