Listado de todos los extras de una intención

251

Por razones de depuración, quiero enumerar todos los extras (y sus valores) de una Intención. Ahora, obtener las llaves no es un problema

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

pero obtener los valores de las claves es uno para mí, porque algunos valores son cadenas, algunos son booleanos ... ¿Cómo podría obtener los valores en un bucle (recorrer las teclas) y escribir los valores en un archivo de registro? Gracias por cualquier pista!

stefan.at.wpf
fuente

Respuestas:

467

Esto es lo que solía obtener información sobre una intención indocumentada (de terceros):

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

Asegúrese de verificar si bundlees nulo antes del bucle.

kshahar
fuente
2
Me acabo de enterar de la aplicación para Android Intent Intercept . Eso tambien funciona.
Vinayak
1
if (bundle == null) { return; }FTW
Matyas
23
Bundle bundle = data.getExtras();¿Dónde dataestá la intención? Para principiantes de Android.
ConquerorsHaki
2
Antes de iniciar sesión, debe verificar si el valor es nulo, de ser así, hágalo value = "null".
Sebastian Kreft
¡Gracias por esto! Estaba buscando una manera de verificar todas las claves que se proporcionaron en esta aplicación iTracing no documentada, para controlar mi teléfono a través de un botón Bluetooth barato. ¡Trabajado como un encanto!
Shane Smiskol
111

Así es como defino el método de utilidad para volcar todos los extras de un 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");
    }
}
Pratik
fuente
8
¡Gracias! Ahora, si solo el equipo de Android comenzara a implementar anulaciones útiles de .toString como esta.
Jim Vitek
37

Puedes hacerlo en una línea de código:

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

Produce algo como:

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

Al final de esta cadena (la parte en negrita) puede encontrar la lista de extras (solo uno adicional en este ejemplo).

Esto está de acuerdo con la documentación de toUri : "El URI contiene los datos del Intent como el URI base, con un fragmento adicional que describe la acción, categorías, tipo, indicadores, paquete, componente y extras".

Alex Vang
fuente
3
Si solo desea depurar y ver cuáles son los contenidos de la intención, esta es la mejor opción. Muchas gracias
Shyri
Esta debería ser la respuesta aceptada. ¡Perfecto para la depuración de registros!
Ethan Arnold
12
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());
    }
}
usuario123321
fuente
8

El método get (String key) de Bundle devuelve un Object. Su mejor opción es girar sobre el conjunto de teclas llamando a get (String) en cada tecla y usando toString () en el Objeto para generarlas. Esto funcionará mejor para las primitivas, pero puede encontrar problemas con los Objetos que no implementan un toString ().

nicholas.hauschild
fuente
4
Bundle extras = getIntent().getExtras();
Set<String> ks = extras.keySet();
Iterator<String> iterator = ks.iterator();
while (iterator.hasNext()) {
    Log.d("KEY", iterator.next());
}
Luis
fuente
1
for (String key: extras.keySet ()) {Log.d (LOG_TAG, key + ":" + extras.get (key)); }
Defuera
4

Quería una forma de generar el contenido de una intención en el registro y poder leerlo fácilmente, así que esto es lo que se me ocurrió. Creé una LogUtilclase, y luego tomé el dumpIntent()método que @Pratik creó y lo modifiqué un poco. Así es como se ve todo:

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

¡Espero que esto ayude a alguien!

LukeWaggoner
fuente
2

Puede usar for (String key : keys) { Object o = get(key);para devolver un objeto, getClass().getName()invocarlo para obtener el tipo y luego hacer un conjunto de cosas de tipo if name.equals ("String") para determinar a qué método debería llamar realmente, para obtener el valor ?

Ben Williams
fuente
1

Noté en la fuente de Android que casi todas las operaciones obligan al paquete a desempaquetar sus datos. Entonces, si (como yo) necesita hacer esto con frecuencia para fines de depuración, lo siguiente es muy rápido para escribir:

Bundle extras = getIntent().getExtras();
extras.isEmpty(); // unparcel
System.out.println(extras);
Ian Lovejoy
fuente
0

Lo siento si esto es demasiado detallado o demasiado tarde, pero esta fue la única forma que pude encontrar para hacer el trabajo. El factor más complicado fue el hecho de que Java no tiene funciones de paso por referencia, por lo que los métodos get --- Extra necesitan un valor predeterminado para devolver y no pueden modificar un valor booleano para determinar si el valor predeterminado se devuelve o no por casualidad, o porque los resultados no fueron favorables. Para este propósito, hubiera sido mejor hacer que el método generara una excepción que devolver un valor predeterminado.

Encontré mi información aquí: Documentación de intención de Android .

    //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

Establecer documentación

    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
fuente
No desea escribir tanto código para hacer esta cosa simple a menos que quiera complicar tanto su código que está seguro de que nunca podrá obtener una actualización de su aplicación. Las respuestas de Top-2 hacen esto con mucho menos código, y usando Log, que es mejor que Toast para tales usos
Louis CAD
0

La versión de Kotlin del método de utilidad de Pratik que descarga todos los extras de un 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")

}
romano
fuente
1
Sería más fácil de usarfor (key in bundle.keySet())
DDoSolitary
-2

Si para la depuración, todo lo que desea es una cadena (algo implícito en el OP pero no se indica explícitamente), simplemente use toStringen los extras Bundle:

intent.getExtras().toString()

Devuelve una cadena como:

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

Documentación: Bundle.toString () (desafortunadamente es el Object.toString()javadoc predeterminado y, como tal, bastante inútil aquí).

ralfoide
fuente
44
Cuando probé esto, devuelve: Bundle [mParcelledData.dataSize = 480]
ToddH