Cannot Receive_SMS

Owais Ahmed 81 Reputation points
2021-02-07T08:48:36.613+00:00

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 Main Activity ,Manifest and SmsReciver files are given below ,I've shared the code on github also! github.com/owais19

//----------------- Main Activity ----------------------

[Activity(Label = "@ hide /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 ----------------------

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"

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,366 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 77,256 Reputation points Microsoft Vendor
    2021-02-08T09:22:26.147+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    I notice you use Android 9.0, if you want to read sms, you should change your application as SMS default application like following screenshot.

    65382-sms1.png

    Firstly, we should set my application to the default sms app.

    We must do following steps(If we lack of one of them, it will not worked).

    • In a broadcast receiver, include an intent filter for SMS_DELIVER_ACTION ("android.provider.Telephony.SMS_DELIVER"). The broadcast receiver must also require the BROADCAST_SMS permission. This allows your app to directly receive incoming SMS messages.
    • In a broadcast receiver, include an intent filter for WAP_PUSH_DELIVER_ACTION ("android.provider.Telephony.WAP_PUSH_DELIVER") with the MIME type "application/vnd.wap.mms-message". The broadcast receiver must also require the BROADCAST_WAP_PUSH permission. This allows your app to directly receive incoming MMS messages.
    • In your activity that delivers new messages, include an intent filter for ACTION_SENDTO ("android.intent.action.SENDTO") with schemas, sms:, smsto:, mms:, and mmsto:. This allows your app to receive intents from other apps that want to deliver a message.
    • In a service, include an intent filter for ACTION_RESPONSE_VIA_MESSAGE ("android.intent.action.RESPOND_VIA_MESSAGE") with schemas, sms:, smsto:, mms:, and mmsto:. This service must also require the SEND_RESPOND_VIA_MESSAGE permission.

    Without all four, your app will not be listed in the default SMS selection dialog.

    Here is edited Manifest file.

       <manifest xmlns:android="http://schemas.android.com/apk/res/android"   
                 android:versionCode="1"   
                 android:versionName="1.0"   
                 package="com.companyname.sms_receiver2">  
         <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />  
         <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">  
         
           <!-- BroadcastReceiver that listens for incoming MMS messages -->  
         
           <receiver android:name=".MmsReceiver"  
               android:permission="android.permission.BROADCAST_WAP_PUSH">  
             <intent-filter>  
               <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />  
               <data android:mimeType="application/vnd.wap.mms-message" />  
             </intent-filter>  
           </receiver>  
           <!-- Activity that allows the user to send new SMS/MMS messages -->  
         
           <activity android:name=".ComposeSmsActivity" >  
             <intent-filter>  
               <action android:name="android.intent.action.SEND" />  
               <action android:name="android.intent.action.SENDTO" />  
               <category android:name="android.intent.category.DEFAULT" />  
               <category android:name="android.intent.category.BROWSABLE" />  
               <data android:scheme="sms" />  
               <data android:scheme="smsto" />  
               <data android:scheme="mms" />  
               <data android:scheme="mmsto" />  
             </intent-filter>  
           </activity>  
         
           <!-- Service that delivers messages from the phone "quick response" -->  
           <service android:name=".HeadlessSmsSendService"  
                    android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"  
                    android:exported="true" >  
             <intent-filter>  
               <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />  
               <category android:name="android.intent.category.DEFAULT" />  
               <data android:scheme="sms" />  
               <data android:scheme="smsto" />  
               <data android:scheme="mms" />  
               <data android:scheme="mmsto" />  
             </intent-filter>  
           </service>  
         
         
         
         
         </application>  
         
         <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
         <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
         <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
         <uses-permission android:name="android.permission.READ_SMS" />  
         <uses-permission android:name="android.permission.SEND_SMS" />  
         <uses-permission android:name="android.permission.RECEIVE_SMS" />  
         <uses-permission android:name="android.permission.BROADCAST_SMS" />  
         
       </manifest>  
    

    Then add following three class

       public class MmsReceiver : BroadcastReceiver  
           {  
               public override void OnReceive(Context context, Intent intent)  
               {  
                   Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();  
               }  
           }  
         
         
         public class HeadlessSmsSendService : Service  
           {  
               public override IBinder OnBind(Intent intent)  
               {  
                   return null;  
               }  
           }  
         
         public class ComposeSmsActivity : Activity  
           {  
               protected override void OnCreate(Bundle savedInstanceState)  
               {  
                   base.OnCreate(savedInstanceState);  
         
                   // Create your application here  
               }  
           }  
    

    In the end, change the default app with following code.

       //Add this to make your app default  
                   Intent intent = new Intent();  
                   intent.SetAction(Telephony.Sms.Intents.ActionChangeDefault);  
                   intent.PutExtra(Telephony.Sms.Intents.ExtraPackageName, "com.companyname.sms_receiver2");  
    

    Here is your Receiver1.cs.

       using Android.App;  
       using Android.Content;  
       using Android.OS;  
       using Android.Runtime;  
       using Android.Views;  
       using Android.Widget;  
       using System;  
       using System.Collections.Generic;  
       using System.Linq;  
       using System.Text;  
       using Android.Telephony;  
       using Android.Provider;  
       using Android.Database;  
       using Android.Util;  
         
       namespace Sms_Receiver2  
       {  
           [BroadcastReceiver(Enabled = true, Exported = true, Permission = "android.permission.BROADCAST_SMS")]  
           [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" })]  
           public class Receiver1 : BroadcastReceiver  
           {  
               public string message = "";  
               public string address = "";  
               public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";  
         
               public Receiver1()  
               {  
         
               }  
         
                 public string Text { get; set; }  
               public override void OnReceive(Context context, Intent intent)  
               {  
                   var msgs = Telephony.Sms.Intents.GetMessagesFromIntent(intent);  
         
                   List<string> msgList = new List<string>();  
                   string address = "";  
                   string body = "";  
                   foreach (var msg in msgs)  
                   {  
                       msgList.Add(msg.DisplayMessageBody);  
                       address = msg.DisplayOriginatingAddress;  
                       body = msg.DisplayMessageBody;  
         
         
                   }  
                   markMessageRead(Android.App.Application.Context, address, body);  
         
                   Text = body;  
                   Toast.MakeText(context, "Number :" + address + "Message : " + body, ToastLength.Short).Show();  
         
                   // MessagingCenter.Send<List<string>>(msgList, "MyMessage");  
               }  
         
         
               public void markMessageRead(Context context, String number, String body)  
               {  
         
                   Android.Net.Uri uri = Android.Net.Uri.Parse("content://sms/inbox");  
                   ICursor cursor = context.ContentResolver.Query(uri, null, null, null, null);  
                   try  
                   {  
         
                       while (cursor.MoveToNext())  
                       {  
                           if ((cursor.GetString(cursor.GetColumnIndex("address")).Equals(number)) && (cursor.GetInt(cursor.GetColumnIndex("read")) == 0))  
                           {  
                               if (cursor.GetString(cursor.GetColumnIndex("body")).StartsWith(body))  
                               {  
                                   String SmsMessageId = cursor.GetString(cursor.GetColumnIndex("_id"));  
                                   ContentValues values = new ContentValues();  
                                   values.Put("read", true);  
                                   context.ContentResolver.Update(Android.Net.Uri.Parse("content://sms/inbox"), values, "_id=" + SmsMessageId, null);  
                                   return;  
                               }  
                           }  
                       }  
                   }  
                   catch (Exception e)  
                   {  
                       Log.Error("Mark Read", "Error in Read: " + e.ToString());  
                   }  
               }  
           }  
            
       }  
    

    Here is your MainActivity.cs

       [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]  
           public class MainActivity : AppCompatActivity  
           {  
         
                Receiver1 _receiver;        // Receiver class   
               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);  
         
                   if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadSms) != (int)Permission.Granted)  
                   {  
                       RequestPermissions(new string[] { Manifest.Permission.ReadSms, Manifest.Permission.SendSms, Manifest.Permission.ReceiveSms }, 0);  
                   }  
         
                   //Add this to make your app default  
                   Intent intent = new Intent();  
                   intent.SetAction(Telephony.Sms.Intents.ActionChangeDefault);  
                   intent.PutExtra(Telephony.Sms.Intents.ExtraPackageName, "com.companyname.sms_receiver2");  
         
         
                   StartActivity(intent);  
         
         
         
         
                   translateButton.Click += (s, e) =>  
                   {  
                       translatedPhoneWord.Text = _receiver.Text;  
         
                       // = _receiver.message;  
                       // Toast.MakeText(ApplicationContext, _receiver.address + ", " + _receiver.message, ToastLength.Short).Show();     //showing a Toast again   
         
                   };  
         
         
                   //  RegisterReceiver(_receiver,new IntentFilter();  
         
               }  
               public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)  
               {  
                   Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);  
         
                   base.OnRequestPermissionsResult(requestCode, permissions, grantResults);  
               }  
         
         
               protected override void OnResume()  
               {  
                   base.OnResume();  
                   _receiver = new Receiver1();  
         
                   IntentFilter filter = new IntentFilter();  
                   filter.AddAction("android.provider.Telephony.SMS_RECEIVED");  
                   filter.AddAction("android.provider.Telephony.SMS_DELIVER");  
         
                   RegisterReceiver(_receiver, filter);  
               }  
         
               protected override void OnPause()  
               {  
                   base.OnPause();  
                   UnregisterReceiver(_receiver);  
         
               }  
         
           }  
       }  
    

    Here is running screenshot( when you run your application, please gave the sms permission and change the default sms application).

    65342-sms2.png

    ============================
    Update=================================

    Somehow, I checked on this ,Uninstalled my App,Redeployed it on my phone (Android 9.0), It first asked my about the default permission which I cancelled,Then it >asked me for permissions for sending and reading sms.My App worked regardless that I made it default or not in my case I didn't,so thats a relief,but when I destroy >my App start it again it asks me about the default permission again which it should just one time after installation.How can I make it stop asking me everytime I start >my App?

    You can use Preferences to achieve it when you first login. If you are loging at the first time, myValue is true, if push the window, Preferences.Set("IsFirstLogin", false); will be setted to false, at the next time, this window that asks you about the default permission will not execute.

       bool myValue = Preferences.Get("IsFirstLogin", true);  
         
                   if (myValue)  
                   {  
                       //Add this to make your app default  
                       Intent intent = new Intent();  
                       intent.SetAction(Telephony.Sms.Intents.ActionChangeDefault);  
                       intent.PutExtra(Telephony.Sms.Intents.ExtraPackageName, "com.companyname.sms_receiver2");  
         
         
                       StartActivity(intent);  
         
                       Preferences.Set("IsFirstLogin", false);  
                   }  
    

    Best Regards,

    Leon Lu


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.