My carrier (I live in Venezuela) is constantly sending me SMS, some of it is crap, some of it I care about, I dont really want to download an SMS app from the market since im doing something very specific and simple.
Basic idea: I have a BroadcastReceiver
that captures the SMS recived intent, in order to be nice to the OS, I dont do any processing here (I want to be able to build rules as complex as I can think of and not have long running issues, maybe using DB or other Asynchronous tasks that cant be done in a BroadcastReceiver
), instead I send the same Bundle to an IntentService
that processes the SMS.
This works fine in general, I can stop the broadcast if I want to avoid having the System notice I got an SMS, and the IntentService
processes the SMS perfectly.
Issue:
How do I process the SMS in the service and then decide wether or not I wanted the System to notice I got an SMS?
I strongly would like to avoid doing the procesing inside the BroadcastReceiver
. (This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.)
I had though of processing the SMS, and if didnt match my criteria, I could re-issue the SMS Recive broadcast with an aditional extra in the bundle to check wether or not it had been previously verified. But I cant get this to work.
Code:
public class SmsReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if(!intent.getExtras().getBoolean("previouslyChecked",false)){
this.abortBroadcast();
Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
serviceIntent.putExtras(intent);
context.startService(serviceIntent);
}
}
}
public class SmsRecievedServices extends IntentService {
public SmsRecievedServices() {
super("SmsRecievedServices");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle bundle = intent.getExtras();
if(!smsMatchesCriteria(bundle)){
Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
bundle.putBoolean("previouslyChecked",true);
intent2.putExtras(bundle);
sendOrderedBroadcast(intent2,"android.permission.RECEIVE_SMS");
}
}
}
The broadcast reciever gets the intent and doesnt cancel the broadcast, but the system doesnt pick up on the SMS. Any ideas?
Edit (In response to Blundell's comment):
I thought about the fact that maybe me adding an extra would ruin it, so I tried the following:
public class SmsReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
int randomNum = (int)Math.ceil(Math.random()*100);
if(randomNum > 20){
this.abortBroadcast();
Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
serviceIntent.putExtras(intent);
context.startService(serviceIntent);
}
}
}
public class SmsRecievedServices extends IntentService {
public SmsRecievedServices() {
super("SmsRecievedServices");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i("SMSManager","Forwarding intent");
Bundle bundle = intent.getExtras();
Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
intent2.putExtras(bundle);
sendOrderedBroadcast(intent2, "android.permission.RECEIVE_SMS");
}
}
LogCat output is:
02-10 22:06:24.632: I/SMSManager(424): RandomNumber: 74
02-10 22:06:24.673: I/SMSManager(424): Forwarding intent
02-10 22:06:24.683: I/SMSManager(424): RandomNumber: 64
02-10 22:06:24.803: I/SMSManager(424): Forwarding intent
02-10 22:06:24.824: I/SMSManager(424): RandomNumber: 28
02-10 22:06:24.832: I/SMSManager(424): Forwarding intent
02-10 22:06:24.854: I/SMSManager(424): RandomNumber: 14
As you can see, the message was hidden from the system three times, the fourth time im not calling abort broadcast as the randomNumber is lower than 20. The OS does not show a new SMS, neither in inbox or notification bar.