Broadcast Receiver not being called
Asked Answered
G

3

6

I am trying to build a simple app that will wait until a new SMS arrives, extract and process the data from it. The application should run in the background. The GUI has a single switch element to start/stop the broadcast receiver. Even if the app is destroyed and the screen is locked, the app should still be working unless the user manually turns it off. I searched every resource on stackoverflow, and most of them did it this way, yet, it still does not work for me, and I can't seem to know why. I know because Log.d(...) is not returning anything. Any help would be appreciated.

enter image description here

Broadcast SMS Receiver

public class SMSReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("RECEIVER", "ENTERED");

        if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
            Log.d("RECEIVER", "SMS RECEIVED");

            SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
            for(int i = 0; i < 4; i++){
                SmsMessage sms = messages[i];
                Log.d("Message " + i + 1 + " from: ", sms.getOriginatingAddress());
                Toast.makeText(context,"SMS from " + sms.getOriginatingAddress(), Toast.LENGTH_SHORT).show();
            }
        }

    }
}

Main Activity

public class MainActivity extends AppCompatActivity {
    IntentFilter filter;
    SMSReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        receiver = new SMSReceiver();

        Switch startSwitch = (Switch) findViewById(R.id.startSwitch);
        startSwitch.setChecked(false);

        startSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if(isChecked){
                    getApplication().registerReceiver(new SMSReceiver(), filter);
                } else {
                    getApplication().unregisterReceiver(receiver);
                }
            }
        });

    }
}

Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ahmad.smsforwarder">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

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

</manifest>
Groupie answered 4/3, 2017 at 17:54 Comment(1)
Where is your Receiver on Manifest?Alundum
G
7

I suffered too long to find out that as of Android 6.0 (API 23), you will have to register permissions in the main activity java class as well. I fixed the problem by adding the following lines to the main activity's class onCreate() Method:

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_SMS},1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS},1);
Groupie answered 19/3, 2017 at 17:47 Comment(1)
Note that these two lines won't work if together, you have to request them one at a time. They will result in a log statement "2020-04-17 17:11:41.286 10156-10156/com.example.myapplication W/Activity: Can request only one set of permissions at a time" but from UI side it will be a silent bug.Corinthian
G
6

You have to register your receiver in AndroidManifest.xml with specific intent in intent filter.

    <receiver
        android:name=".SMSReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
Godard answered 4/3, 2017 at 18:4 Comment(0)
F
0

Please use smsRetrieverAPI (message template requires app hash string in the end)or smsUserConsentAPI (message template doesn't require app hash string in the end). These google APIs don't require SMS read permission anymore.

Sms Retriever API https://developers.google.com/identity/sms-retriever/request

Sms User Consent API https://developers.google.com/identity/sms-retriever/user-consent/overview

<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"
          android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
    </intent-filter>
</receiver>
Fults answered 8/4, 2023 at 4:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.