Anil P Babu
Anil P Babu

Reputation: 1315

Broadcast Receiver for RECEIVE_SMS is not working when declared in manifest(statically)

I am trying to detect SMS received and read it via texttospeech.

when i declare the Broadcast Receiver in manifest it doesn't work. But it works when done dynamically in an activity.

I am aware that some Broadcast actions cant be caught in a receiver when declared in manifest and requires an activity(as mentioned here), but have seen people using RECEIVE_SMS in manifest as in here.

I don't know what I am doing wrong. Any help would be greatly appreciated!

AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.bulsy.smstalk1">
        <uses-permission android:name="android.permission.RECEIVE_SMS" />
        <uses-permission android:name="android.permission.READ_SMS" />
        <uses-permission android:name="android.permission.SEND_SMS"/>
        <uses-permission android:name="android.permission.READ_CONTACTS" />

        <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>
            <receiver android:name="com.bulsy.smstalk1.SmsListener"
                   android:enabled="true" 
                   android:permission="android.permission.BROADCAST_SMS"
                   android:exported="true">   
                <intent-filter android:priority="2147483647">//this doesnt work
                    <category android:name="android.intent.category.DEFAULT" />
                    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                </intent-filter>
            </receiver>
        </application>   
    </manifest>

SmsListener.java

public class SmsListener extends BroadcastReceiver{

    private SharedPreferences preferences;
    TextToSpeech textToSpeech;
    String msg_from;
    public SmsListener()
    {

    }

    @Override
    public void onReceive(final Context context, Intent intent) {
        // TODO Auto-generated method stub
        if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){

            Bundle bundle = intent.getExtras();           //---get the SMS message passed in---
            SmsMessage[] msgs = null;

            if (bundle != null){
                //---retrieve the SMS message received---
                try{
                    Object[] pdus = (Object[]) bundle.get("pdus");
                    msgs = new SmsMessage[pdus.length];
                    for(int i=0; i<msgs.length; i++){
                        msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
                        msg_from = msgs[i].getOriginatingAddress();
                        final String msgBody = msgs[i].getMessageBody();
                        textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
                            @Override
                            public void onInit(int status) {
                                if(status != TextToSpeech.ERROR) {
                                    textToSpeech.setLanguage(Locale.UK);
                                    String fromName = getContactName(context,msg_from);
                                    fromName = fromName==null? msg_from:fromName;
                                    textToSpeech.speak("You have a text message from " + fromName + ". Content: " + msgBody , TextToSpeech.QUEUE_FLUSH, null);
                                }
                            }
                        }
                        );


                    }
                }catch(Exception e){
//                            Log.d("Exception caught",e.getMessage());
                }
            }
        }
    }

MainActivity.java

    public class MainActivity extends AppCompatActivity {

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

        SmsListener smsListener = new SmsListener();//Dynamically setting the receiver. this works.
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        this.registerReceiver(smsListener,filter);
    }
}

Upvotes: 2

Views: 1644

Answers (1)

Mike M.
Mike M.

Reputation: 39191

The root of the problem here is the lifetime of a manifest-registered Receiver instance. An instance of such a Receiver will only be alive until the onReceive() method completes. The TextToSpeech object will not be ready before the Receiver dies, and without any other indication of the Receiver working, it appears as though the Receiver has just failed.

The solution is to move the TextToSpeech functionality to a Service you can run from the Receiver, and pass the necessary info as extras on the Intent used to start it.

Upvotes: 2

Related Questions