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)
Advertisement
Answer
This was probably a false alarm; it’s more likely due to our own instance variable being null:
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"; private State state; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); state = initializeState(); // MISSING NULL CHECK HERE! Bundle extras = getIntent().getExtras(); if (extras == null) { finish(); return; } // do stuff with state and extras } }