Перечисление всех дополнений намерения

251

По причинам отладки я хочу перечислить все дополнения (и их значения) намерения. Теперь получить ключи не проблема

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

но получение значений ключей - одно для меня, потому что некоторые значения являются строками, некоторые - логическими ... Как я могу получить значения в цикле (циклически перебирая ключи) и записать значения в файл журнала? Спасибо за любую подсказку!

stefan.at.wpf
источник

Ответы:

467

Вот что я использовал для получения информации о недокументированном (стороннем) намерении:

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

Убедитесь, что проверили, bundleявляется ли нуль перед циклом.

kshahar
источник
2
Я только что узнал о приложении Intent Intercept для Android . Это тоже работает.
Винаяк
1
if (bundle == null) { return; }FTW
Матиас
23
Bundle bundle = data.getExtras();Где dataнамерение. Для начинающих Android.
ЗавоевателиХаки
2
Перед регистрацией необходимо проверить, является ли значение пустым, если это так value = "null".
Себастьян Крефт
Спасибо за это! Искал способ проверить все ключи, которые были предоставлены в этом недокументированном приложении iTracing, чтобы управлять моим телефоном с помощью дешевой кнопки Bluetooth. Работал как шарм!
Шейн Смискол
111

Вот как я определяю служебный метод для сброса всех дополнительных функций 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
источник
8
Спасибо! Теперь, если только команда Android начнет реализовывать полезные переопределения .toString, как это.
Джим Витек
37

Вы можете сделать это в одной строке кода:

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

Это выводит что-то вроде:

"#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; конец "

В конце этой строки (часть, которую я выделил) вы можете найти список дополнений (только один дополнительный в этом примере).

Это в соответствии с документацией toUri : «URI содержит данные Интента в качестве базового URI с дополнительным фрагментом, описывающим действие, категории, тип, флаги, пакет, компонент и дополнительные элементы».

Алекс Ванг
источник
3
Если вы просто хотите отладить и посмотреть, каково содержание намерения, это лучший вариант. Большое спасибо
Шири
Это должен быть принятый ответ. Идеально подходит для отладки журналов!
Итан Арнольд
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
источник
8

Метод get (String key) из Bundle возвращает объект. Лучше всего прокрутить набор ключей, вызывая get (String) для каждой клавиши и используя toString () для Object для их вывода. Это будет работать лучше всего для примитивов, но вы можете столкнуться с проблемами с объектами, которые не реализуют toString ().

nicholas.hauschild
источник
4
Bundle extras = getIntent().getExtras();
Set<String> ks = extras.keySet();
Iterator<String> iterator = ks.iterator();
while (iterator.hasNext()) {
    Log.d("KEY", iterator.next());
}
Луис
источник
1
for (строковый ключ: extras.keySet ()) {Log.d (LOG_TAG, ключ + ":" + extras.get (ключ)); }
Defuera
4

Мне нужен был способ вывести содержимое намерения в журнал и чтобы его можно было легко прочитать, поэтому вот что я придумал. Я создал LogUtilкласс, а затем взял dumpIntent()метод @Pratik и немного его изменил. Вот как это все выглядит:

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

Надеюсь, это поможет кому-то!

LukeWaggoner
источник
2

Вы можете использовать, for (String key : keys) { Object o = get(key);чтобы вернуть Object, вызвать getClass().getName()его, чтобы получить тип, а затем выполнить набор типов if name.equals ("String"), чтобы выяснить, какой метод вы на самом деле должны вызывать, чтобы получить значение ?

Бен Уильямс
источник
1

В источнике Android я заметил, что почти каждая операция вынуждает Bundle разархивировать свои данные. Так что, если (как и мне) вам нужно делать это часто для целей отладки, приведенный ниже текст можно набрать очень быстро:

Bundle extras = getIntent().getExtras();
extras.isEmpty(); // unparcel
System.out.println(extras);
Йен Лавджой
источник
0

Извините, если это слишком многословно или слишком поздно, но это был единственный способ найти работу. Наиболее сложным фактором был тот факт, что java не имеет функций обхода по ссылкам, поэтому методам get --- Extra необходимо возвращать значение по умолчанию, и он не может изменить логическое значение, чтобы определить, было ли возвращено значение по умолчанию случайно, или потому что результаты не были благоприятны. Для этой цели было бы лучше, если бы метод вызывал исключение, а не возвращал значение по умолчанию.

Я нашел свою информацию здесь: Документация по 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

Задать документацию

    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();
    }
Джексон Кулик
источник
Вы не хотите писать так много кода, чтобы делать эту простую вещь, если не хотите усложнять свой код настолько, чтобы быть уверенным, что никогда не сможете обновить свое приложение. Топ-2 ответов делают это с гораздо меньшим количеством кода и использованием журнала, который лучше, чем тосты, для таких случаев
Louis CAD
0

Kotlin-версия служебного метода Pratik, который сбрасывает все дополнения 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")

}
Римский
источник
1
Было бы проще использоватьfor (key in bundle.keySet())
DDoSolitary
-2

Если для отладки все, что вам нужно, это строка (вроде как подразумевается OP, но явно не указано), просто используйте toStringв дополнениях Bundle:

intent.getExtras().toString()

Возвращает строку, такую ​​как:

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

Документация: Bundle.toString () (к сожалению, это Object.toString()javadoc по умолчанию, и здесь он совершенно бесполезен.)

ralfoide
источник
4
Когда я попробовал это, он возвращает: Bundle [mParcelledData.dataSize = 480]
ToddH