In Activity.onCreate(), why does Intent.getExtras() sometimes return null?

Ten-Young Guh picture Ten-Young Guh · Aug 9, 2013 · Viewed 17k times · Source

This was probably a false alarm, see my own answer. Original question below:

An activity has a button that takes the user to another activity. To launch the new activity, we populate our Intent with extras, and onCreate(), the new activity reads from those extras via Intent.getExtras(). We assumed the returned bundle would be non-null, but as customer crash reports discovered, getExtras() sometimes returns null.

Null-guarding the extras, as this answer shows, is perfectly fine, but if you populate the intent's extras, then why would it ever return null later? Is there a better place (like onResume()) to read the extras?

EDIT: It may be because we are not following the name convention required for the keys:

The name must include a package prefix, for example the app com.android.contacts would use names like "com.android.contacts.ShowAll".

This is from the Intent.putExtras javadoc. What happens if you don't follow this name convention; is the behavior even defined?

Here's the relevant code:

class FromActivity extends Activity {

    ImageButton button;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.from_view);

        button = (ImageButton)findViewById(R.id.button);
        button.setVisibility(View.VISIBLE);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(FromActivity.this, ToActivity.class);
                i.putExtra(ToActivity.SERVER_PARAM, ...);
                i.putExtra(ToActivity.UUID_PARAM, ...);
                i.putExtra(ToActivity.TEMPLATE_PARAM, ...);
                startActivityForResult(i, 0); 
                overrideTransition(R.anim.slide_left_in, R.anim.slide_left_out);
            }
        });
    }

}

class ToActivity extends Activity {

    public static final String SERVER_PARAM = "server";
    public static final String UUID_PARAM = "uuid";
    public static final String TEMPLATE_PARAM = "template";

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

        Bundle extras = getIntent().getExtras();
        if (extras == null) {
            finish();
            return;
        }

        // do stuff with extras
    }
}

Here is a sample stack trace of this problem:

java.lang.RuntimeException: Unable to start activity ComponentInfo{ToActivity}: java.lang.NullPointerException
    at  android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2355)
    at  android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
    at  android.app.ActivityThread.access$600(ActivityThread.java:151)
    at  android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
    at  android.os.Handler.dispatchMessage(Handler.java:99)
    at  android.os.Looper.loop(Looper.java:155)
    at  android.app.ActivityThread.main(ActivityThread.java:5493)
    at  java.lang.reflect.Method.invokeNative(Native Method)
    at  java.lang.reflect.Method.invoke(Method.java:511)
    at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
    at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
    at  dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
    at  ToActivity.onCreate(SourceFile:49)
    at  android.app.Activity.performCreate(Activity.java:5066)
    at  android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)
    at  android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
     ... 11 more
     java.lang.NullPointerException
    at  ToActivity.onCreate(SourceFile:49)
    at  android.app.Activity.performCreate(Activity.java:5066)
    at  android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)
    at  android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
    at  android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
    at  android.app.ActivityThread.access$600(ActivityThread.java:151)
    at  android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
    at  android.os.Handler.dispatchMessage(Handler.java:99)
    at  android.os.Looper.loop(Looper.java:155)
    at  android.app.ActivityThread.main(ActivityThread.java:5493)
    at  java.lang.reflect.Method.invokeNative(Native Method)
    at  java.lang.reflect.Method.invoke(Method.java:511)
    at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
    at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
    at  dalvik.system.NativeStart.main(Native Method)

Answer

Martin Cazares picture Martin Cazares · Aug 9, 2013

You can get it like this:

getIntent().getStringExtra(key);

Or:

getIntent().getExtras().getString(key)

And set it like this in "FromActivity":

Bundle extras = new Bundle();
extras.putString(key, value);
intent.putExtras(extras);
//And start your activity...

Or:

intent.putExtra(key, string);
//And start your activity...

Either way should work, Hope this helps...

Regards!