5

I'm new to Android/Java. I'd like to write a test application where any arbitrary extra that I add to a (custom) intent is printed. When I receive the intent with my BroadcastReceiver, I can get all the extras as Bundle and their keys by:

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

How do I find out what is the type of a value associated with a given key?

What I was thinking is something like:

Object tmp = bundle.get(key);
// utilize https://stackoverflow.com/questions/709961/

But this way doesn't seem to be the best idea. Another option seems to be something like:

if (bundle.getBoolean(key) == null) {
    // can't determine if `null` was explicitly associated or not
} else if /* ... */

but this way I cannot determine if the null value was intended or not. I could create a custom default value class, but I'm not sure this is the intended way. edit I've just realized I need a default value of the same type, so I can't even do this. (One could double-check for null and a custom default typed value to know, though.)

How do I know the type of a value for a given key dynamically?

Community
  • 1
  • 1
n611x007
  • 8,952
  • 8
  • 59
  • 102
  • You can use "instanceof" to know what kind of object is linked to a key. About last point, if you get a null for a key it means that it was done on purpose any other way it won't exist that key in the set. – Juangcg Oct 22 '13 at 13:21
  • 1
    Maybe this answer can help you: http://stackoverflow.com/a/7163619/2065418 – Damien R. Oct 22 '13 at 13:24
  • @Juangcg but in case of getBoolean it should return a primitive-type `boolean` - does `instanceof` work with primitive types at all? – n611x007 Oct 22 '13 at 13:27
  • @naxa you should retrieve the object with "Object tmp = bundle.get(key);" then make instanceof Boolean (the object not the primitive type). If it returns true, you just need to ((Boolean)tmp).boolValue() – Juangcg Oct 22 '13 at 13:29
  • @Juangcg I've realized from DamienR's link that you may mean *instanceof* with the *autoboxed* *wrapper* types `Integer`, etc. because I need to use `Object` in `Object tmp = bundle.get(key)` which will autobox the primitive into a wrapper type anyway . I see you wrote the same, I was slow :) Thanks! – n611x007 Oct 22 '13 at 13:29

3 Answers3

6

Maybe I should explain me better through an answer better than a comment.

You can do what you want doing this.

Object tmp = bundle.get(key);
if (tmp instanceof Boolean) {
    boolean finalValue = ((Boolean)tmp).booleanValue();
}

If you check the source from Android you will see something similar, they always pass the wrapper not the primitive type.

public boolean More ...getBoolean(String key, boolean defaultValue) {
    Object o = mMap.get(key);
    if (o == null) {
        return defaultValue;
    }
    try {
        return (Boolean) o;
    } catch (ClassCastException e) {
        typeWarning(key, o, "Boolean", defaultValue, e);
        return defaultValue;
    }
}

The difference is that they do not check the type of the object as they suppose you know what you are doing.

source

Juangcg
  • 1,038
  • 9
  • 14
1

I believe you cant determine the type, if you send the intent then you know what to receive, if you are receiving intent from other application just read their documentation. They would document it if they want you to use it :)

Ahmad Dwaik 'Warlock'
  • 5,953
  • 5
  • 34
  • 56
  • I see. But maybe my test application is to explore any undocumented intent? :) – n611x007 Oct 22 '13 at 13:33
  • like what? excuse me I'm just curious :) – Ahmad Dwaik 'Warlock' Oct 22 '13 at 13:34
  • 1
    Nothing top secret actually, we co-work with a company and their documentation and specs are sometimes ambiguous, missing or change without notice. We exchange emails about it but it is not the fastest thing so you just want to know what really is happening in the new drop of their code, if for nothing else then to pinpoint what is wrong/missing in the documentation. – n611x007 Oct 22 '13 at 13:38
  • Yes co-workers can be pain in the ass, i say that again "They would document it if they want you to use it" – Ahmad Dwaik 'Warlock' Oct 22 '13 at 13:45
  • may be very well true, still it doesn't cover documentation errors or ambiguity. – n611x007 Oct 22 '13 at 14:00
0

This is an old question but I offer IMHO an elegant new solution.

    //@ Dump key types in bundle
   void showKeyTypesInBundle(
            Bundle bundle)  // bundle to query
    {
        // Notes:
        // 'print()' is my output function (e.g. Log.i).
        // keys with null values are not shown.

        int size;
        Set<String> ks = bundle.keySet();   // get keys in bundle
        size = ks.size();                   // get key count

        print( "KEYS IN BUNDLE:" );
        if( size > 0 ) {                    // any keys in bundle?
            for (String key : ks ) {        // for every key in keyset...
                String type = getKeyType(bundle, key);  // get type
                print("  key \"" + key + "\": type =\"" + type + "\"");
            }
        }
        else {                               // no keys in bundle?
            print( "  No Keys found" );
        }
        print( "END BUNDLE." );
    }

    //@ Get type of bundle key
    String getKeyType(
            Bundle bundle,  // bundle containing key
            String key)     // key name

    {
        Object keyobj;
        String type;

        if( bundle == null || key == null ) return( null );     // bad call/

        keyobj = bundle.get( key );                             // get key as object
        if( keyobj == null ) return( null );                    // not present?
        type = keyobj.getClass().getName();                     // get class name
        return( type );
        // Returns name of key value type
        // e.g. "java.lang.String" or "java.lang.Integer"
        // or null on error        }
    }

If desired, you can call bundle.getXXX based on type, e.g. bundle.getString() if type is "java.lang.String".

DontPanic
  • 2,164
  • 5
  • 29
  • 56