14

After going through several resources and questions, I still face a problem with detecting an incoming SMS message.

The code below shows the basics:

Broadcast receiver class that displays toast onReceive

public class IncomingSms extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "something received", Toast.LENGTH_SHORT).show();
    }
}

Simple Manifest with registering receiver and permissions

<application
    <receiver 
        android:name=".IncomingSms"
        android:permission="android.permission.BROADCAST_SMS"
        android:exported="true">

        <intent-filter android:priority="2147483647" >
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>

</application>

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

The code above declares and registers the receiver, and has proper permissions. In addition, the priority is set to MAX_INT, or 2147483647.

My device is Nexus 6P, with default Messenger app installed (I also tried Hangouts). The app still does not display my toasts. After trying on an older Samsung device, the toasts were printed properly.

Priority issue

I installed on the 6P an app called Manifest Viewer, which allows me to see the manifest.xml of apps installed on my device. I checked the manifests of both Messenger and Hangouts, for the receiver of SMS tag, and found that both of them also specify a priority of 2147483647. It seems like both those messenger apps max out the priority, and once they consume the message, they don't allow other applications to intervene. Note that these are stock Google apps, and not 3rd party.

At this point, I am quite confused as to:

  • why would they do this?
  • how to bypass it?

Thanks a lot

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
Khorkhe
  • 1,024
  • 1
  • 11
  • 26

2 Answers2

40

Okay the problem was resolved. The issue did not reside with priorities, but with my phone being a Nexus 6P (a.k.a. API 23).

Providing permissions in the manifest.xml alone wasn't enough and I had to add code for runtime permission request. See Android documentation for runtime permissions

Add this code to your MainActiviy:

ActivityCompat.requestPermissions(this, 
            new String[]{Manifest.permission.RECEIVE_SMS},
            MY_PERMISSIONS_REQUEST_SMS_RECEIVE);

Define this at the top of MainActivity Class:

private int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10;

And also add this override:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_SMS_RECEIVE) {
        // YES!!
        Log.i("TAG", "MY_PERMISSIONS_REQUEST_SMS_RECEIVE --> YES");
    }
}
Oded Regev
  • 4,065
  • 2
  • 38
  • 50
Khorkhe
  • 1,024
  • 1
  • 11
  • 26
  • Also got Nexus 6P. Thanks what i needed! Thanks – RJB Jul 11 '16 at 19:28
  • 2
    Thank you, great post, very helpful. Although I got the impression that the problem is more related to the API level 23 and not the Nexus device. And perhaps you should note that the last override is not really required, just for code copy zombies like me out there ;-) – anhoppe Apr 05 '17 at 20:00
  • @anhoppe yea they should give a heads up that you need to do this if you're running at api version >= 23 – committedandroider Jul 16 '18 at 08:00
  • 2
    This solved my problems - I was only requesting `READ_SMS` permissions but not `RECEIVE_SMS` permission. Even though I followed a tutorial on Android Authority! – Magnus Sep 19 '18 at 08:28
  • Wonderful answer! It happens in API level 30, Pixel Device. – Youngsup Kim Jul 17 '20 at 09:07
  • You need to check the grantResults array to see if your app really received the permission – MrObjectOriented Jun 26 '21 at 11:11
  • Perfect this worked for me. – Manoj I Jun 25 '23 at 07:51
2

Please make sure your implementation is like this.

SMS Receiver class

    public class SmsReceiver extends BroadcastReceiver {

        private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(SMS_RECEIVED)) {
                Bundle bundle = intent.getExtras();
                if (bundle != null) {
                    // get sms objects
                    Object[] pdus = (Object[]) bundle.get("pdus");
                    if (pdus.length == 0) {
                        return;
                    }
                    // large message might be broken into many
                    SmsMessage[] messages = new SmsMessage[pdus.length];
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < pdus.length; i++) {
                        messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                        sb.append(messages[i].getMessageBody());
                    }
                    String sender = messages[0].getOriginatingAddress();
                    String message = sb.toString();
                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
                    // prevent any other broadcast receivers from receiving broadcast
                    // abortBroadcast();
                }
            }
        }
    }

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.smsreceiver"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="4" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity
           // your activity
        </activity>
        <receiver android:name="com.example.smsreceiver.SmsReceiver" android:enabled="true">
            <intent-filter android:priority="2147483647">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Make sure you use your own defined package. package defined here is dummy.

Adnan Amjad
  • 2,553
  • 1
  • 20
  • 29
  • I would like to first make sure I detect anything in "onReceive" before delving into a more detailed implementation. I tried your snippets just to confirm, and there is still no output. I still believe it has to do with the priority set on the Nexus' stock apps. – Khorkhe Mar 13 '16 at 13:03
  • Check this tutorial if you have if it may help you. http://androidexample.com/Incomming_SMS_Broadcast_Receiver_-_Android_Example/index.php?view=article_discription&aid=62&aaid=87 – Adnan Amjad Mar 13 '16 at 13:12
  • Just for check. Force close both of sms applications from settings. and then test your app. – Adnan Amjad Mar 13 '16 at 13:40
  • Issue isn't the implementation of the broadcast register or registration of it in the manifest. You need to require additional app permissions like the top answer recommended – committedandroider Jul 16 '18 at 08:02