Reputation: 1315
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
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