[android] Listing all extras of an Intent

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!

This question is related to android android-intent

The answer is


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."


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();
    }

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");
    }
}

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")

}

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);

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!


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());
    }
}

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?


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.


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.)


Bundle extras = getIntent().getExtras();
Set<String> ks = extras.keySet();
Iterator<String> iterator = ks.iterator();
while (iterator.hasNext()) {
    Log.d("KEY", iterator.next());
}

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().