Update Intent extras between ordered BroadcastReceivers android
I am currently getting the SMS_Received Broadcast from the system and am attempting to change the values in the intent before the other broadcastreceivers get it, (such as the default messaging app)
However, no matter what way I try and change the intent, the broadcast listeners do not see the updated values. And because the system does not let you send out a SMS_Received broadcast I cannot abort this one and resend one out. Am I doing something wrong or is there no way this can be done?
//Some example code I开发者_Go百科 have tried
Intent updatedIntent = changeIncomingIntent(intent, context);
intent.putExtras(updatedIntent.getExtras());
intent.replaceExtras(updatedIntent.getExtras());
You can't change the received intent, but if you're... hehe... intending to modify a received SMS, because it's an ordered broadcast, you can stop the broadcast, modify the intent's extras, and then rebroadcast it:
Add the following to your ApplicationManifest.xml before the Application tag:
<uses-permission android:name="android.permission.BROADCAST_SMS" />
Note that this will appear on your app's permissions page in the Play Store. Be prepared to explain it.
And add this to the Intent-Filter tag in your Receiver:
android:priority="2147483647"
That's the highest possible integer in Java, ensuring that your receiver gets first priority. Note that receivers in other applications (notably GO SMS) might be using this same strategy, which may mean that the two receivers end up fighting over a message. If this happens, you'll probably have to uninstall the other app.
And then in your receiver:
public void onReceive(Context context, Intent intent){
//Messages are delivered as extras in the intent
Bundle bundle = intent.getExtras();
//If this intent was rebroadcasted already, ignore it.
if(bundle.getBooleanExtra("rebroadcast", false)
return;
//Abort the broadcast
abortBroadcast();
//Some examples use regular arrays,
// but I prefer a more sophisticated solution.
ArrayList<SmsMessage> msgs = new ArrayList<SmsMessage>();
//Check to make sure we actually have a message
if(bundle != null){
//Get the SMS messages
//They are delivered in a raw format,
//called Protocol Description Units or PDUs
//Messages can sometimes be delivered in bulk,
//so that's why it's an array
Object[] pdus = (Object[]) bundle.get("pdus");
//I prefer the enhanced for-loop. Why reinvent the wheel?
for(Object pdu : pdus)
msgs.add(SmsMessage.createFromPdu((byte[])pdu));
//Do stuff with the message.
ArrayList<SmsMessage> newMessages = smsReceived(msgs);
//Convert back to PDUs
ArrayList<Object> pdus;
Iterator<SmsMessage> iterator = newMessages.iterator();
//Iterate over the messages and convert them
while(iterator.hasNext()){
pdus.add(iterator.next().getPdu())
}
//Convert back to an Object[] for bundling
Object[] pduArr = pdus.toArray();
//Redefine the intent.
//It already has the broadcast action on it,
//so we just need to update the extras
bundle.putExtra("pdus", pduArr);
//Set a rebroadcast indicator so we don't process it again
//and create an infinite loop
bundle.putExtra("rebroadcast", true);
intent.putExtras(bundle);
//Finally, broadcast the modified intent with the original permission
sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
else{
//For some reason, there was no message in the message.
//What do you plan to do about that? I'd just ignore it.
}
}
While this is a functional example, I would recommend doing most of this in a new Thread so as to not block the UI thread if your message handling is processor-intensive. For example, I did it in mine because I employ a lot of regex to manipulate the message, as well as perform some pretty heavy database queries in relation to the message.
If I did something wrong or could have done better, please don't hesitate to correct me. Most of this code is in my own project and I'd like to be able to guarantee its functionality.
Have a nice day.
(1) You can't just modify the Intent object. That is a local object only for your instance.
(2) There are APIs for resulting data back from the receiver (setting the result and such), but you can only use these if the broadcast is being sent as a ordered broadcast. Very few are sent this way; the documentation should say when they are.
Note that broadcasts are normally parallel, so it makes no sense to try to change what others will receive -- they could very well be executing at the exact same time you are.
精彩评论