Search code examples
androidbroadcastreceiversms

SMS Broadcast Receiver in Oreo+


I am trying to intercept SMS messages delivered to my device. I wrote an app to do that a year or so ago, and I find it is no longer catching messages (even though code is unchanged).

I don't believe it is permission-related. I tried compiling under SDK 23 (requiring runtime permissions) and SDK 22 (no runtime permissions). (In the case of 23, I verified that permission RECEIVE_SMS is successfully granted).

Most questions/answers about this issue are quite old. IMHO The answers didn't seem enlightened, e.g. adding BROADCAST_SMS permission, invoking native code, etc.

My approach was to implement a broadcast receiver. Code excepts below.

BROADCAST RECEIVER

//  SmsRecv.java - SMS Receiver    

package com.ramrod.SmsReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class SmsRecv extends BroadcastReceiver {

    //@ Handler for received sms messages
    @Override
    public void onReceive(
        Context ctx,
        Intent intent)
    {    
        // NEVER REACHED!
        Main.toast( "SMS RECEIVED." );
        // PROCESS MESSAGE HERE...    
    }

MANIFEST

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ramrod.SmsReceiver"
      android:versionCode="100"
      android:versionName="1.00">

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

    <application
      android:icon="@drawable/icon"
      android:label="SmsReceiver"
      android:theme="@android:style/Theme"
    >
      <activity android:name=".Main"
            android:label="SmsReceiver"
          >
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>

      <receiver android:name=".SmsRecv"
          android:exported="true"
          android:enabled="true"
          >
          <intent-filter android:priority="999999" >
              <action android:name="android.provider.Telephony.SMS_RECEIVED" />
          </intent-filter>
      </receiver>

    </application>
</manifest>

BUILD.GRADLE

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "27.0.3"

    defaultConfig {
        applicationId "com.ramrod.SmsReceiver"
        minSdkVersion 23
        targetSdkVersion 23
    }
    ...

Tested on Samsung S7 running Oreo V8.0.0. I tested this by sending text messages from another phone. These were received correctly but never triggered SmsRecv().

In my reading, I encountered the notion that now an SMS broadcast receiver will no longer work unless it is the default SMS app on the device (huh?).

Any suggestions greatly appreciated.


Solution

  • I finally figured out what was wrong. Apparently, Android version Oreo+ does not deliver implicit broadcasts any more* (i.e., those specified in the manifest file <receiver>). You now must explicitly register your receiver (i.e., with registerReceiver()) in your code.

    (*Note: Mike M correctly pointed out that received SMS broadcasts are excluded from this restriction according to Android doc, but nonetheless this was not so for me in practice).

    So what I did to make this work was:

    • Completely Remove <receiver> from manifest.
    • Create an instance of my receiver and an intentFilter in my activities onCreate();

          MyReceiver = new SmsRecv();
          MyFilter   = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION );  
      
    • Register the receiver in my Activity's onResume().

          i = registerReceiver( MyReceiver, MyFilter);  
      
    • Unregister the receiver in my Activity's onPause(). (This is neccessary to prevent leaks).

          unregisterReceiver( MyReceiver );
      

    With the changes, the app worked perfectly.