306

For debugging reasons I want to list all extras (and their values) of an Intent. Now, getting the keys isn't a problem

Set<String> keys = intent.getExtras().keySet();

but getting the values of the keys is one for me, because some values are strings, some are boolean... How could I get the values in a loop (looping through the keys) and write the values to a logfile? Thanks for any hint!

stefan.at.kotlin
  • 15,347
  • 38
  • 147
  • 270

14 Answers14

557

Here's what I used to get information on an undocumented (3rd-party) intent:

Bundle bundle = intent.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        Log.e(TAG, key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
    }
}

Make sure to check if bundle is null before the loop.

Sean McManus
  • 137
  • 2
  • 11
kshahar
  • 10,423
  • 9
  • 49
  • 73
  • 3
    I just found out about [Intent Intercept Android app](https://github.com/intrications/intent-intercept). That works too. – Vinayak Mar 02 '15 at 14:36
  • 1
    `if (bundle == null) { return; }` FTW – Matyas Nov 07 '15 at 17:36
  • 27
    `Bundle bundle = data.getExtras();` Where `data` is the Intent. For android beginners. – Ahmed Hasn. Feb 02 '16 at 13:31
  • 2
    Before logging you need to check whether the value is null, if so do `value = "null"`. – Sebastian Kreft Feb 12 '16 at 03:48
  • Thanks for this! Was looking for a way to check all the keys that was provided in this undocumented iTracing app, to control my phone via a cheap Bluetooth button. Worked like a charm! – Shane Smiskol Jul 23 '17 at 01:57
  • @Sebastian Kreft Above kshahar and one of the other commenters recommend checking if the bundle == null. Your comment recommends checking if "value" == null. Do you mean checking each individual "key" to make sure they are not null, after checking if the bundle is not null? – AJW Jun 02 '20 at 20:10
  • @AJW, the code was updated and now includes my comment. Please check the history of the answer. – Sebastian Kreft Jun 03 '20 at 04:42
  • @Sebastian Kreft How do I see the history of the answer to know it was updated with your feedback? All I see is that the answer was edited in Yr2019, 3+ years after your comment. But I can't tell what was edited...or am I missing something? – AJW Jun 03 '20 at 06:23
  • @AJW next to the name of the person who answered it says it was edited and there's a link to the revisions. https://stackoverflow.com/posts/15074150/revisions – Sebastian Kreft Jun 03 '20 at 18:54
  • @Sebastian Kreft I never knew one could click the link to see revisions. I appreciate your reply...you are a gentleman and a scholar. Cheers. – AJW Jun 04 '20 at 20:12
113

This is how I define utility method to dump all extras of an Intent.

import java.util.Iterator;
import java.util.Set;
import android.os.Bundle;


public static void dumpIntent(Intent i){

    Bundle bundle = i.getExtras();
    if (bundle != null) {
        Set<String> keys = bundle.keySet();
        Iterator<String> it = keys.iterator();
        Log.e(LOG_TAG,"Dumping Intent start");
        while (it.hasNext()) {
            String key = it.next();
            Log.e(LOG_TAG,"[" + key + "=" + bundle.get(key)+"]");
        }
        Log.e(LOG_TAG,"Dumping Intent end");
    }
}
rsc
  • 10,348
  • 5
  • 39
  • 36
Pratik
  • 1,596
  • 2
  • 13
  • 10
65

You can do it in one line of code:

Log.d("intent URI", intent.toUri(0));

It outputs something like:

"#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10a00000;component=com.mydomain.myapp/.StartActivity;sourceBounds=12%20870%20276%201167; l.profile=0; end"

At the end of this string (the part that I bolded) you can find the list of extras (only one extra in this example).

This is according to the toUri documentation: "The URI contains the Intent's data as the base URI, with an additional fragment describing the action, categories, type, flags, package, component, and extras."

TechAurelian
  • 5,561
  • 5
  • 50
  • 65
17

A Kotlin solution useful for evaluation in debug mode:

// list: List<Pair<String!, Any?>>?
val list = intent.extras?.keySet()?.map { it to (intent.extras?.get(it) ?: "null") }

Log.d("list", list.toString();

That would print the list of all extras in the bundle extras

Thiago
  • 12,778
  • 14
  • 93
  • 110
ruX
  • 7,224
  • 3
  • 39
  • 33
  • Good answer but it is safer to use optionals as: val list = intent.extras?.keySet()?.map { it to (intent.extras?.get(it) ?: "null") } – Thiago Nov 03 '22 at 13:50
16
private TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    tv = new TextView(this);
    tv.setText("Extras: \n\r");

    setContentView(tv);

    StringBuilder str = new StringBuilder();
    Bundle bundle = getIntent().getExtras();
    if (bundle != null) {
        Set<String> keys = bundle.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String key = it.next();
            str.append(key);
            str.append(":");
            str.append(bundle.get(key));
            str.append("\n\r");
        }
        tv.setText(str.toString());
    }
}
user123321
  • 12,593
  • 11
  • 52
  • 63
8

The get(String key) method of Bundle returns an Object. Your best bet is to spin over the key set calling get(String) on each key and using toString() on the Object to output them. This will work best for primitives, but you may run into issues with Objects that do not implement a toString().

nicholas.hauschild
  • 42,483
  • 9
  • 127
  • 120
6

I wanted a way to output the contents of an intent to the log, and to be able to read it easily, so here's what I came up with. I've created a LogUtil class, and then took the dumpIntent() method @Pratik created, and modified it a bit. Here's what it all looks like:

public class LogUtil {

    private static final String TAG = "IntentDump";

    public static void dumpIntent(Intent i){
        Bundle bundle = i.getExtras();
        if (bundle != null) {
            Set<String> keys = bundle.keySet();

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("IntentDump \n\r");
            stringBuilder.append("-------------------------------------------------------------\n\r");

            for (String key : keys) {
                stringBuilder.append(key).append("=").append(bundle.get(key)).append("\n\r");
            }

            stringBuilder.append("-------------------------------------------------------------\n\r");
            Log.i(TAG, stringBuilder.toString());
        }
    }
}

Hope this helps someone!

LukeWaggoner
  • 8,869
  • 1
  • 29
  • 28
4
Bundle extras = getIntent().getExtras();
Set<String> ks = extras.keySet();
Iterator<String> iterator = ks.iterator();
while (iterator.hasNext()) {
    Log.d("KEY", iterator.next());
}
Luis
  • 535
  • 2
  • 14
2

I noticed in the Android source that almost every operation forces the Bundle to unparcel its data. So if (like me) you need to do this frequently for debugging purposes, the below is very quick to type:

Bundle extras = getIntent().getExtras();
extras.isEmpty(); // unparcel
System.out.println(extras);
Ian Lovejoy
  • 376
  • 4
  • 7
2

You could use for (String key : keys) { Object o = get(key); to return an Object, call getClass().getName() on it to get the type, and then do a set of if name.equals("String") type things to work out which method you should actually be calling, in order to get the value?

Ben Williams
  • 6,027
  • 2
  • 30
  • 54
2

Get it as a string separated with "," in Kotlin!

val extras = intent?.extras?.keySet()?.map { "$it: ${intent.extras?.get(it)}" }?.joinToString { it }

based on ruX answer.

Sergio
  • 2,346
  • 2
  • 24
  • 28
1

The Kotlin version of Pratik's utility method which dumps all extras of an Intent:

fun dumpIntent(intent: Intent) {

    val bundle: Bundle = intent.extras ?: return

    val keys = bundle.keySet()
    val it = keys.iterator()

    Log.d(TAG, "Dumping intent start")

    while (it.hasNext()) {
        val key = it.next()
        Log.d(TAG,"[" + key + "=" + bundle.get(key)+"]");
    }

    Log.d(TAG, "Dumping intent finish")

}
Roman
  • 774
  • 7
  • 12
0

Sorry if this is too verbose or too late, but this was the only way I could find to get the job done. The most complicating factor was the fact that java does not have pass by reference functions, so the get---Extra methods need a default to return and cannot modify a boolean value to tell whether or not the default value is being returned by chance, or because the results were not favorable. For this purpose, it would have been nicer to have the method raise an exception than to have it return a default.

I found my information here: Android Intent Documentation.

    //substitute your own intent here
    Intent intent = new Intent();
    intent.putExtra("first", "hello");
    intent.putExtra("second", 1);
    intent.putExtra("third", true);
    intent.putExtra("fourth", 1.01);
    // convert the set to a string array

Set Documentation

    String[] anArray = {};
    Set<String> extras1 = (Set<String>) intent.getExtras().keySet();
    String[] extras = (String[]) extras1.toArray(anArray);
    // an arraylist to hold all of the strings
    // rather than putting strings in here, you could display them
    ArrayList<String> endResult = new ArrayList<String>();
    for (int i=0; i<extras.length; i++) {
        //try using as a String
        String aString = intent.getStringExtra(extras[i]);
        // is a string, because the default return value for a non-string is null
        if (aString != null) {
            endResult.add(extras[i] + " : " + aString);
        }
        // not a string
        else {
            // try the next data type, int
            int anInt = intent.getIntExtra(extras[i], 0);
            // is the default value signifying that either it is not an int or that it happens to be 0 
            if (anInt == 0) {
                // is an int value that happens to be 0, the same as the default value
                if (intent.getIntExtra(extras[i], 1) != 1) {
                    endResult.add(extras[i] + " : " + Integer.toString(anInt));
                }
                // not an int value
                // try double (also works for float)
                else {
                    double aDouble = intent.getDoubleExtra(extras[i], 0.0);
                    // is the same as the default value, but does not necessarily mean that it is not double
                    if (aDouble == 0.0) {
                        // just happens that it was 0.0 and is a double
                        if (intent.getDoubleExtra(extras[i], 1.0) != 1.0) {
                            endResult.add(extras[i] + " : " + Double.toString(aDouble));
                        }
                        // keep looking...
                        else {
                            // lastly check for boolean
                            boolean aBool = intent.getBooleanExtra(extras[i], false);
                            // same as default, but not necessarily not a bool (still could be a bool)
                            if (aBool == false) {
                                // it is a bool!
                                if (intent.getBooleanExtra(extras[i], true) != true) {
                                    endResult.add(extras[i] + " : " + Boolean.toString(aBool));
                                }
                                else {
                                    //well, the road ends here unless you want to add some more data types
                                }
                            }
                            // it is a bool
                            else {
                                endResult.add(extras[i] + " : " + Boolean.toString(aBool));
                            }
                        }
                    }
                    // is a double
                    else {
                        endResult.add(extras[i] + " : " + Double.toString(aDouble));
                    }
                }
            }
            // is an int value
            else {
                endResult.add(extras[i] + " : " + Integer.toString(anInt));
            }
        }
    }
    // to display at the end
    for (int i=0; i<endResult.size(); i++) {
        Toast.makeText(this, endResult.get(i), Toast.LENGTH_SHORT).show();
    }
Jackson Kulik
  • 308
  • 2
  • 10
  • 1
    You don't want to write so much code to do this simple thing unless you want to complicate your code so much you are certain to never be able to get an update to your app done. Top-2 answers do this with much less code, and using Log, which is better than Toasts for such usages – Louis CAD Sep 13 '16 at 13:36
-2

If for debugging all you want is a string (sort of implied by the OP but not explicitly stated), simply use toString on the extras Bundle:

intent.getExtras().toString()

It returns a string such as:

Bundle[{key1=value1, key2=value2, key3=value3}]

Documentation: Bundle.toString() (it's unfortunately the default Object.toString() javadoc and as such quite useless here.)

ralfoide
  • 2,705
  • 4
  • 23
  • 21