11

I am implementing an activity that responds to the RecognizerIntent. Among others this activity must handle two incoming extras that specify a pending intent and its extras-bundle:

  • EXTRA_RESULTS_PENDINGINTENT
  • EXTRA_RESULTS_PENDINGINTENT_BUNDLE

Paraphrasing the documentation:

  • If you use EXTRA_RESULTS_PENDINGINTENT to supply a PendingIntent, the results will be added to its bundle and the PendingIntent will be sent to its target.

  • If you use EXTRA_RESULTS_PENDINGINTENT to supply a forwarding intent, you can also use EXTRA_RESULTS_PENDINGINTENT_BUNDLE to supply additional extras for the final intent. The search results will be added to this bundle, and the combined bundle will be sent to the target.

I have been looking in vain for sample code that would demonstrate the following.

What is the best way of extracting a PendingIntent from a bundle?

Should I do:

(PendingIntent)
        extras.getParcelable(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT)

How to add extras to the set of existing extras of a PendingIntent?

How to launch the modified PendingIntent?

Kaarel
  • 10,554
  • 4
  • 56
  • 78
  • Please check below link it is source of searchDialog.java you can deep study that and you can may be clear your answer. http://www.devdaily.com/java/jwarehouse/android/core/java/android/app/SearchDialog.java.shtml – Nikhil Jun 29 '11 at 10:21

3 Answers3

4

You can not directly touch the contents of a PendingIntent, for security reasons. However, when you send the PendingIntent, you have the opportunity to supplement or modify its contents depending on what the original creator allows.

This is the method you want to use to send the PendingIntent:

http://developer.android.com/reference/android/app/PendingIntent.html#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler)

The Intent you supply here is the data used to modify the final Intent sent from the PendingIntent.

The rules for what can be modified are here:

http://developer.android.com/reference/android/content/Intent.html#fillIn(android.content.Intent, int)

Note that by default when a PendingIntent is created, the only parts that can be modified by the sender are the extras. The creator can pass in flags to allow other parts to be modified, although this is generally not desired.

hackbod
  • 90,665
  • 16
  • 140
  • 154
  • 1
    You're welcome. I should clarify a bit -- the default rules for filling in an Intent is that only the extras can be modified, but other fields can be set if they do not already contain data. For example, by default you won't be able to change the action if that is already set. The creator of the PendingIntent can use the flags to say that senders are allowed to modify that field... but of course that opens them to significant security issues, because it means whoever they give the PendingIntent to can modify it to do something very different. – hackbod Jul 01 '11 at 23:25
  • If I am using PendingIntent.getBroadcast to get the PI, what special steps do I need to force it to preserve it existing Intent extras the PI was initially create with? I'm trying to above method, but the extras always wind up null. – Michael Apr 27 '13 at 22:07
1

I might be able to give you a little help with your second question as I have done something similar in my own app.

Adding extras to an intent should be as easy as calling putExtra() on the intent. I have done this for a notification.

Intent notificationIntent = new Intent(_context, MyActivity.class); notificationIntent.putExtra("SOME_ID", "VALUE");

This is part of a notification that launches my app. I later read the extra when my activity resumes.

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if(extras !=null)
{
   String value = extras.getString("SOME_ID");
   if( value != null && value.equals( "VALUE" ) )
   {
      //Value was found, do something
   }
}

Hope this helps some.

Lysandus
  • 764
  • 4
  • 23
1

These are my current answers to these questions. It works like this in a number of Google apps (Maps, Docs, YouTube, Listen) which all pass the PendingIntent to the RecognizerIntent when you perform the search via the microphone button. I am unsure though if this is the best (or most general) way of doing it. Any comments are welcome.

What is the best way of extracting a PendingIntent from a bundle?

Parcelable extraResultsPendingIntentAsParceable =
           bundle.getParcelable(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT);
if (extraResultsPendingIntentAsParceable != null) {
    if (extraResultsPendingIntentAsParceable instanceof PendingIntent) {
        mExtraResultsPendingIntent =
                         (PendingIntent) extraResultsPendingIntentAsParceable;
    } else {
        // Report an error
    }
}

mExtraResultsPendingIntentBundle =
          bundle.getBundle(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE);

How to add extras to the set of existing extras of a PendingIntent?

Here we just create a new intent and put all the required extras into it.

if (mExtraResultsPendingIntentBundle == null) {
    mExtraResultsPendingIntentBundle = new Bundle();
}               
Intent intent = new Intent(); 
intent.putExtras(mExtraResultsPendingIntentBundle);
// Unsure about the following line...
// Should I use another name for the extra data (instead of SearchManager.QUERY)
intent.putExtra(SearchManager.QUERY, speechRecognitionResult);

How to launch the modified PendingIntent?

We send off the PendingIntent giving it the new intent (with the new extras) as an argument.

try {           
    mExtraResultsPendingIntent.send(this, 1234, intent);
} catch (CanceledException e) {
    // Handle exception
}
Kaarel
  • 10,554
  • 4
  • 56
  • 78
  • 1
    @IgorG. I'm not sure I understand... All the input to the above code comes from the extras. – Kaarel Oct 30 '12 at 15:46