关于android:列出Intent的所有额外内容

Listing all extras of an Intent

出于调试的原因,我想列出一个意图的所有附加项(及其值)。现在,拿到钥匙不是问题

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

但是获取键的值对我来说是一个,因为有些值是字符串,有些是布尔值…如何获取循环中的值(循环遍历键)并将值写入日志文件?谢谢你的提示!


以下是我过去获得的关于无文件(第三方)意图的信息:

1
2
3
4
5
6
7
8
Bundle bundle = data.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        Object value = bundle.get(key);
        Log.d(TAG, String.format("%s %s (%s)", key,
                value.toString(), value.getClass().getName()));
    }
}

其中data是意图。循环前一定要检查bundle是否为空。


这就是我如何定义实用程序方法来转储一个意图的所有额外部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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");
    }
}


您可以在一行代码中执行此操作:

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

它输出如下内容:

"intent;action=android.intent.action.main;category=android.intent.category.launcheflags=0x100000;component=com.mydomain.myapp/.startactivity;sourcebunds=12%20870%20276%201167;l.profile=0;end"

在这个字符串的末尾(我用粗体显示的部分),您可以找到附加项列表(本例中只有一个附加项)。

这是根据Touri文档:该URI包含作为基URI的意向数据,还有一个描述操作、类别、类型、标志、包、组件和附加项的附加片段。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private TextView tv;

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

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

");

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

");
        }
        tv.setText(str.toString());
    }
}

bundle的get(string key)方法返回一个对象。最好的方法是对每个键调用get(string)并在对象上使用toString()来输出它们的键集进行旋转。这对基元最有效,但可能会遇到与未实现ToString()的对象有关的问题。


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


我想要一种方法将一个意图的内容输出到日志中,并且能够很容易地读取它,所以下面是我想到的方法。我创建了一个LogUtil类,然后采用了dumpIntent()方法@pratik created,并对其进行了一些修改。这就是它的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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

");
            stringBuilder.append("-------------------------------------------------------------

");

            for (String key : keys) {
                stringBuilder.append(key).append("=").append(bundle.get(key)).append("

");
            }

            stringBuilder.append("-------------------------------------------------------------

");
            Log.i(TAG, stringBuilder.toString());
        }
    }
}

希望这能帮助别人!


您可以使用for (String key : keys) { Object o = get(key);返回一个对象,调用该对象上的getClass().getName()来获取类型,然后执行一组if-name.equals("string")类型的操作来计算您实际应该调用哪个方法来获取值?


我在android源代码中注意到,几乎每个操作都会迫使包取消对其数据的分析。因此,如果(像我一样)为了调试的目的需要经常这样做,那么下面的输入速度非常快:

1
2
3
Bundle extras = getIntent().getExtras();
extras.isEmpty(); // unparcel
System.out.println(extras);

Pratik实用方法的Kotlin版本,它转储了一个意图的所有额外内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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")

}


抱歉,如果这太冗长或太晚,但这是我能找到的唯一方法完成工作。最复杂的因素是Java不具有通过引用功能,因此get -额外方法需要默认返回,并且不能修改布尔值来判断默认值是否是偶然返回的,还是因为结果不好。为此,让方法引发异常比让它返回默认值要好。

我在这里找到了我的信息:android意向文档。

1
2
3
4
5
6
7
    //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

设置文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    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();
    }


如果要调试的只是一个字符串(某种程度上由op隐含,但没有明确说明),只需在附加的bundle上使用toString

1
intent.getExtras().toString()

它返回一个字符串,例如:

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

文档:bundle.toString()(不幸的是,它是默认的Object.toString()javadoc,因此在这里非常无用。)