Forum Xamarin.Android

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Cannot Receive SMS

Ow19mOw19m Member ✭✭

I want to receive a message from my application,I've followed a few post discussing about the same topic,tried reproducing the same thing but cant receive a message on my app.When I receive a message a toast pops up ,after that I can click the button and I should see a message on textview and a toast pop again .Can anyone help me point where Im wrong ? My MainActivity ,Manifest and SmsReciver files are given below :

//----------------- MainActivity ----------------------

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private intentReceiver _receiver = new intentReceiver();
private IntentFilter intentFilter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);

        TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneword);
        Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);


        intentFilter = new IntentFilter();
        intentFilter.AddAction("SMS_RECEIEVED_ACTION");


        translateButton.Click += (s, e) =>
        { 

            translatedPhoneWord.Text = _receiver.message;
            Toast.MakeText(ApplicationContext, _receiver.address + ", " + _receiver.message, ToastLength.Short).Show();     //showing a Toast again 

        };

//--------------------- SmsReciever class -----------------------

[BroadcastReceiver]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" },Priority =(int)IntentFilterPriority.HighPriority)]
public class intentReceiver : BroadcastReceiver
{
public string address = "";
public string message = "";

    public override void OnReceive(Context context, Intent intent)
    {

        try
        {

            if (intent.HasExtra("pdus"))
            {
                var smsArray =
                (Java.Lang.Object[])intent.Extras.Get("pdus");

                foreach (var item in smsArray)
                {
                    var sms = SmsMessage.CreateFromPdu((byte[])item);
                    message += sms.MessageBody;
                    address = sms.OriginatingAddress;
                    Toast.MakeText(Application.Context, "From :" + address + "Message :" + message, ToastLength.Long).Show();
                }


                Intent BroadcastIntent = new Intent();
                BroadcastIntent.SetAction("SMS_RECEIEVED_ACTION");
                BroadcastIntent.PutExtra("message", "From :" + address + "Message :" + message);
                context.SendBroadcast(BroadcastIntent);

            }
        }
        catch (Exception e)
        {
            Toast.MakeText(Application.Context, "Error" + e,ToastLength.Long).Show();
        }

    }
}

**// --------------- Manifest File ----------------------
**

<?xml version="1.0" encoding="utf-8"?>











Answers

  • Ow19mOw19m Member ✭✭
    edited January 27

    // --------------- Manifest File ----------------------

    uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"
    uses-permission android:name="android.permission.SEND_SMS"
    uses-permission android:name="android.permission.RECIEVE_SMS"
    uses-permission android:name="android.permission.READ_SMS"
    uses-permission android:name="android.permission.BROADCAST_SMS"
    uses-permission android:name="android.permission.WRITE_SMS"
    uses-permission android:name="android.permission.VIBRATE"

  • jezhjezh Member, Xamarin Team Xamurai

    You can refer to the following code:

        [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
        public class MainActivity : AppCompatActivity, ActivityCompat.IOnRequestPermissionsResultCallback 
        {
            static readonly int REQUEST_SENDSMS = 0;
    
            public  string TAG
            {
                get
                {
                    return "MainActivity";
                }
            }
            static string[] PERMISSIONS_SENDMSG = {
                Manifest.Permission.SendSms,
                Manifest.Permission.ReadPhoneState
            };
    
            View layout;
            private SmsManager _smsManager;
            private BroadcastReceiver _smsSentBroadcastReceiver, _smsDeliveredBroadcastReceiver;
    
            Button smsBtn;
            EditText phoneNum;
            EditText sms;
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                //Xamarin.Essentials.Platform.Init(this, savedInstanceState);
                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.layout1);
                layout = FindViewById(Resource.Id.sample_main_layout);
                smsBtn = FindViewById<Button>(Resource.Id.btnSend);
                phoneNum = FindViewById<EditText>(Resource.Id.phoneNum);
                sms = FindViewById<EditText>(Resource.Id.txtSMS);
                _smsManager = SmsManager.Default;
    
                smsBtn.Click += (s, e) =>
                {
                    checkSendMsgPermission();
    
                };
            }
    
            void checkSendMsgPermission() {
                Log.Info(TAG, "button pressed. Checking permissions.");
    
                // Verify that all required  permissions have been granted.
                if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.SendSms) != (int)Permission.Granted
                    || ActivityCompat.CheckSelfPermission(this, Manifest.Permission.ReadPhoneState) != (int)Permission.Granted)
                {
                    // permissions have not been granted.
                    Log.Info(TAG, " permissions has NOT been granted. Requesting permissions.");
                    RequestSendMsgPermissions();
                }
                else
                {
                    //  permissions have been granted. 
                    Log.Info(TAG, " permissions have already been granted.");
    
                    var phone = phoneNum.Text;
                    var message = sms.Text;
                    var piSent = PendingIntent.GetBroadcast(this, 0, new Intent("SMS_SENT"), 0);
                    var piDelivered = PendingIntent.GetBroadcast(this, 0, new Intent("SMS_DELIVERED"), 0);
                    _smsManager.SendTextMessage(phone, null, message, piSent, piDelivered);
                }
            }
    
            private void RequestSendMsgPermissions()
            {
    
                if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.SendSms)
                    || ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.ReadPhoneState))
                {
    
                    // Display a SnackBar with an explanation and a button to trigger the request.
                    Snackbar.Make(layout, "Message permission is needed to send SMS.",
                        Snackbar.LengthIndefinite).SetAction("OK", new Action<View>(delegate (View obj) {
                            ActivityCompat.RequestPermissions(this, PERMISSIONS_SENDMSG, REQUEST_SENDSMS);
                        })).Show();
                }
                else
                {
                    // Contact permissions have not been granted yet. Request them directly.
                    ActivityCompat.RequestPermissions(this, PERMISSIONS_SENDMSG, REQUEST_SENDSMS);
                }
    
            }
    
    
            protected override void OnResume()
            {
                base.OnResume();
    
                _smsSentBroadcastReceiver = new SMSSentReceiver();
                _smsDeliveredBroadcastReceiver = new SMSDeliveredReceiver();
    
                RegisterReceiver(_smsSentBroadcastReceiver, new IntentFilter("SMS_SENT"));
                RegisterReceiver(_smsDeliveredBroadcastReceiver, new IntentFilter("SMS_DELIVERED"));
            }
    
            protected override void OnPause()
            {
                base.OnPause();
    
                UnregisterReceiver(_smsSentBroadcastReceiver);
                UnregisterReceiver(_smsDeliveredBroadcastReceiver);
            }
    
            public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
            {
    
                if (requestCode== REQUEST_SENDSMS) {
                    if (PermissionUtil.VerifyPermissions(grantResults))
                    {
                        // All required permissions have been granted, display contacts fragment.
                        Snackbar.Make(layout, " Permissions have been granted. ", Snackbar.LengthShort).Show();
                        var phone = phoneNum.Text;
                        var message = sms.Text;
                        var piSent = PendingIntent.GetBroadcast(this, 0, new Intent("SMS_SENT"), 0);
                        var piDelivered = PendingIntent.GetBroadcast(this, 0, new Intent("SMS_DELIVERED"), 0);
                        _smsManager.SendTextMessage(phone, null, message, piSent, piDelivered);
    
                    }
                    else
                    {
                        Log.Info(TAG, " permissions were NOT granted.");
                        Snackbar.Make(layout, "Permissions were not granted.", Snackbar.LengthShort).Show();
                    }
                }
    
                base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            }        
        }
    
        [BroadcastReceiver]
        public class SMSSentReceiver : BroadcastReceiver
        {
            public override void OnReceive(Context context, Intent intent)
            {
                switch ((int)ResultCode)
                {
                    case (int)Result.Ok:
                        Toast.MakeText(Application.Context, "SMS has been sent", ToastLength.Short).Show();
                        break;
                    case (int)SmsResultError.GenericFailure:
                        Toast.MakeText(Application.Context, "Generic Failure", ToastLength.Short).Show();
                        break;
                    case (int)SmsResultError.NoService:
                        Toast.MakeText(Application.Context, "No Service", ToastLength.Short).Show();
                        break;
                    case (int)SmsResultError.NullPdu:
                        Toast.MakeText(Application.Context, "Null PDU", ToastLength.Short).Show();
                        break;
                    case (int)SmsResultError.RadioOff:
                        Toast.MakeText(Application.Context, "Radio Off", ToastLength.Short).Show();
                        break;
                }
            }
        }
    
        [BroadcastReceiver]
        public class SMSDeliveredReceiver : BroadcastReceiver
        {
            public override void OnReceive(Context context, Intent intent)
            {
                switch ((int)ResultCode)
                {
                    case (int)Result.Ok:
                        Toast.MakeText(Application.Context, "SMS Delivered", ToastLength.Short).Show();
                        break;
                    case (int)Result.Canceled:
                        Toast.MakeText(Application.Context, "SMS not delivered", ToastLength.Short).Show();
                        break;
                }
            }                 
        }
    

    The code of layout1.axml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/sample_main_layout">
        <EditText
            android:id="@+id/phoneNum"
            android:hint="phoneNum"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <EditText
            android:id="@+id/txtSMS"
            android:hint="txtSMS"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/btnSend"
            android:text="Send Message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" /> 
    </LinearLayout>
    

    AndroidManifest.xml

     <uses-permission android:name="android.permission.SEND_SMS" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    

    Xamarin forums are migrating to a new home on Microsoft Q&A!
    We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
    For more information, please refer to this sticky post.

  • Ow19mOw19m Member ✭✭

    Am i missing something or did you share a code for sending sms,I have already implemented this ,I'm talking about receiving incoming sms. With due respect ! ,I'm unable to receive any sms,although most people did write something like i have above.

  • jezhjezh Member, Xamarin Team Xamurai

    For this, you can refer to this thread: https://forums.xamarin.com/discussion/180060/xamarin-android-read-sms-inbox-messages

    Hope it can help you.

  • Ow19mOw19m Member ✭✭

    Thanks @jezh but can you atleast just tell me if my code is right or am i doing something wrong ?making a listview is like going around this problem instead of straight.Im not trying to print multiple sms messages here,that I can do after .Ive seen your code,I've basically new to mobile development,from what i can see in the code you specified in the thread is extracting messages from the inbox?

  • Ow19mOw19m Member ✭✭

    I have double checked everything,but i don't understand what Im doing wrong,can anyone point out the problem please!!

  • jezhjezh Member, Xamarin Team Xamurai

    Do you mean you cant receive a message on your app? But I couldn't reproduce this problem on my side by above code I posted.

    Could you please share a basic demo to github or onedriver so that we can test on our side?

  • Ow19mOw19m Member ✭✭

    Sorry for the late reply , Im talking about the code i posted not yours,I checked your code and it worked fine , but I dont want every message on app and im not good enough to write a code to filter it ,because i only want the number I authorize to output on my app.The code above that I mentioned is alot simpler .I've given my github below,Kindly the mistake if you can !

    https://github.com/owais19

  • Ow19mOw19m Member ✭✭

    Any Updates ?Can Anyone Help me on this!

  • Ow19mOw19m Member ✭✭

    I Did change the code a little bit for the receiver but that one should also work ,Maybe Im doing something wrong in my MainActivity even though I did Instantiate the Receiver class and Register the Receiver.If I get stuck on this Im doomed for atleast a 2 week endlessly doing the same thing again and again because there isnt anything more to do with it ,kindly help me out on this anyone ?

  • jezhjezh Member, Xamarin Team Xamurai

    Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. You should request permissions at runtime.

    And READ_SMS is categorized as Dangerous permissions, so you should check this permissions manually for API level 23 and above.

    adorn BroadcastReceiver with the BroadcastReceiverAttribute

    and override the OnReceive method:

        [BroadcastReceiver(Enabled = true, Exported = true, Label = "SMS Receiver")]
        [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" }, Priority = (int)IntentFilterPriority.HighPriority)]
        public class Receiver1 : BroadcastReceiver
        {
            public string message, address = "";
            public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
            public override void OnReceive(Context context, Intent intent)
            {
                Log.Info("123..", "Intent received: " + intent.Action);
    
                context.SendOrderedBroadcast(intent, INTENT_ACTION);
                InvokeAbortBroadcast();
    
                if (intent.HasExtra("pdus"))
                {
                    var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
                    foreach (var item in smsArray)
                    {
                        var sms = SmsMessage.CreateFromPdu((byte[])item);
                        address = sms.OriginatingAddress;
                        message = sms.MessageBody;
                        Toast.MakeText(context, "Number :" + address + "Message : " + message, ToastLength.Short).Show();
    
                    }
                }
    
    
            }
        }
    
  • kaz123kaz123 Member

    Hi,
    am looking for a similar solution.
    @jezh please could you help me. I want to read sms/inbox on the navigating to a page.
    XF
    {
    await Navigation.PushAsync(new SmsListPage());

    am trying to specify address in viewmodel and pass the messages to a viewmodel
    Android class -> pass messages to viewmodel.

        public List<string> GetSMS(Context context)
        {
            var result = new List<string>();
    
            Uri uri = Uri.Parse("content://sms/inbox");
            string[] reqCols = new string[] { "_id", "thread_id", "address", "person", "date", "body", "type" };
            //TODO Assign address name from Viewmodel Or Helper $targetAddress
            var cursor = context.ContentResolver.Query(uri, null, "address='$targetAddress'", null, null);
    
            if (cursor.MoveToFirst())
            {
                do
                {
                    result.Add(cursor.GetString(cursor.GetColumnIndex(reqCols[5])));
                } while (cursor.MoveToNext());
            }
            return result;
    

    I believe I am meant to call this in Mainactivity(Android) then XF? *Total newbie stuck on how.
    Any assistanc will be of great help.

Sign In or Register to comment.