Listando todos os extras de uma Intenção

251

Por razões de depuração, quero listar todos os extras (e seus valores) de um Intent. Agora, obter as chaves não é um problema

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

mas obter os valores das chaves é um para mim, porque alguns valores são strings, outros são booleanos ... Como eu poderia obter os valores em um loop (percorrendo as chaves) e gravar os valores em um arquivo de log? Obrigado por qualquer dica!

stefan.at.wpf
fonte

Respostas:

467

Aqui está o que eu usei para obter informações sobre uma intenção não documentada (de terceiros):

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

Certifique-se de verificar se bundleé nulo antes do loop.

kshahar
fonte
2
Acabei de descobrir sobre o aplicativo Intent Intercept para Android . Isso também funciona.
Vinayak
1
if (bundle == null) { return; }FTW
Matyas
23
Bundle bundle = data.getExtras();Onde dataestá a intenção. Para iniciantes no Android.
ConquerorsHaki #
2
Antes de efetuar o log, é necessário verificar se o valor é nulo, se houver value = "null".
Sebastian Kreft
Obrigado por isso! Estava procurando uma maneira de verificar todas as chaves fornecidas neste aplicativo iTracing não documentado, para controlar meu telefone através de um botão Bluetooth barato. Trabalhou como um encanto!
Shane Smiskol
111

É assim que eu defino o método utilitário para despejar todos os extras de um 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
fonte
8
Obrigado! Agora, se apenas a equipe do Android começar a implementar substituições úteis de .toString como esta.
Jim Vitek
37

Você pode fazer isso em uma linha de código:

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

Ele gera algo como:

"#Intent; ação = android.intent.action.MAIN; categoria = android.intent.category.LAUNCHER; launchFlags = 0x10a00000; componente = com.mydomain.myapp / .StartActivity; sourceBounds = 12% 20870% 20276% 201167; l .profile = 0; final "

No final desta sequência (a parte que eu coloquei em negrito), você pode encontrar a lista de extras (apenas um extra neste exemplo).

Isso está de acordo com a documentação do toUri : "O URI contém os dados do Intent como o URI base, com um fragmento adicional que descreve a ação, categorias, tipo, sinalizadores, pacote, componente e extras".

Alex Vang
fonte
3
Se você deseja apenas depurar e ver qual é o conteúdo da intenção, esta é a melhor opção. Muito obrigado
Shyri
Essa deve ser a resposta aceita. Perfeito para depuração de log!
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());
    }
}
user123321
fonte
8

O método get (String string) do Bundle retorna um Object. Sua melhor aposta é girar sobre o conjunto de teclas chamando get (String) em cada tecla e usando toString () no Object para produzi-las. Isso funcionará melhor para primitivas, mas você pode ter problemas com objetos que não implementam um toString ().

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

Eu queria uma maneira de exibir o conteúdo de uma intenção no log e poder lê-lo facilmente, então aqui está o que eu criei. Eu criei uma LogUtilclasse e, em seguida, peguei o dumpIntent()método @Pratik criado e o modifiquei um pouco. Aqui está o que tudo parece:

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 isso ajude alguém!

LukeWaggoner
fonte
2

Você pode usar for (String key : keys) { Object o = get(key);para retornar um objeto, chamá getClass().getName()-lo para obter o tipo e, em seguida, fazer um conjunto de coisas if.equals ("String") para descobrir qual método você realmente deveria chamar, a fim de obter o valor ?

Ben Williams
fonte
1

Percebi na fonte do Android que quase todas as operações obrigam o Bundle a descompactar seus dados. Portanto, se (como eu) você precisar fazer isso com frequência para fins de depuração, a seguir é muito rápido digitar:

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

Desculpe se isso é muito detalhado ou muito tarde, mas essa foi a única maneira que encontrei para concluir o trabalho. O fator mais complicador foi o fato de o java não possuir funções de referência de passagem. Portanto, os métodos get --- Extra precisam de um padrão para retornar e não podem modificar um valor booleano para saber se o valor padrão está ou não sendo retornado por acaso, ou porque os resultados não foram favoráveis. Para esse propósito, seria melhor ter o método gerar uma exceção do que retornar um padrão.

Encontrei minhas informações aqui: 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

Definir documentação

    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
fonte
Você não deseja escrever tanto código para fazer isso de maneira simples, a menos que queira complicar tanto seu código que certamente nunca conseguirá fazer uma atualização no seu aplicativo. Top-2 respostas fazer isso com muito menos código, e usando Log, que é melhor do que brindes para tais usos
Louis CAD
0

A versão Kotlin do método utilitário do Pratik que despeja todos os extras de um 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
fonte
1
Seria mais simples de usar #for (key in bundle.keySet())
DDoSolitary 16/07/19
-2

Se, para depurar, tudo o que você deseja é uma string (meio implícita no OP, mas não explicitamente declarada), basta usar toStringos extras Bundle:

intent.getExtras().toString()

Retorna uma string como:

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

Documentation: Bundle.toString () (infelizmente é o Object.toString()javadoc padrão e, como tal, bastante inútil aqui.)

ralfoide
fonte
4
Quando tentei isso, ele retorna: Bundle [mParcelledData.dataSize = 480]
ToddH