ScarOnTheSky ScarOnTheSky - 5 months ago 91
Android Question

Using getActivity() in onCreateOptionsMenu() of a fragment occasionally throws an NPE

I'm using a SearchManager in my fragment. Unfortunately, using the method call getActivity().getSystemService(Context.SEARCH_SERVICE) occasionally throws a NullPointerException. This happens both in instrumented Espresso unit tests and during normal usage. When I run the tests again, everything is fine. Can you tell me how to fix this? Thanks.

Stacktrace:

06-05 16:10:59.162 19183 19183 D AndroidRuntime: Shutting down VM
06-05 16:10:59.188 19183 19183 E AndroidRuntime: FATAL EXCEPTION: main
06-05 16:10:59.188 19183 19183 E AndroidRuntime: Process: foo.bar.baz, PID: 19183
06-05 16:10:59.188 19183 19183 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.app.Activity.getSystemService(java.lang.String)' on a null object reference
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at foo.bar.baz.sign_browser.SignBrowserFragment.onCreateOptionsMenu(SignBrowserFragment.java:139)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.Fragment.performCreateOptionsMenu(Fragment.java:2133)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.FragmentManagerImpl.dispatchCreateOptionsMenu(FragmentManager.java:1945)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.Activity.onCreatePanelMenu(Activity.java:2834)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:298)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:241)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:443)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:60)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Looper.loop(Looper.java:135)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5343)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
06-05 16:10:59.227 835 1557 I WindowManager: Screen frozen for +393ms due to AppWindowToken{19c5842b token=Token{34cb447a ActivityRecord{10afa8a5 u0 foo.bar.baz/.activities.MainActivity t4133}}}
06-05 16:10:59.233 835 1557 W ActivityManager: Force finishing activity 1 foo.bar.baz/.activities.MainActivity


SignBrowserFragment.onCreateOptionsMenu()

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d(TAG, "onCreateOptionsMenu " + hashCode());
inflater.inflate(R.menu.options_sign_browser, menu);
final MenuItem item = menu.findItem(R.id.action_toggle_starred);
if (this.showStarredOnly) {
item.setIcon(R.drawable.ic_sign_browser_grade_checked);
} else {
item.setIcon(R.drawable.ic_sign_browser_grade);
}
final SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
}


I'm using the SignBrowserFragment, which is contained with the MainActivity to add the option menu entry for the search. The actual search is performed within the separate SignSearch Activity.

Manifest file:

<activity
android:name=".activities.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<meta-data
android:name="android.app.default_searchable"
android:value=".sign_browser.search.SignSearchActivity" />
</activity>
<activity
android:name=".sign_browser.search.SignSearchActivity"
android:parentActivityName=".activities.MainActivity"
tools:ignore="UnusedAttribute">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>

<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>


Let me know if you need further information.

EDIT: Why is this tagged as a duplicate of "How to fix a NullPointerException"? This is as sensible as tagging it as a duplicate of "How to fix an error". :(

EDIT 2: Sorry, guys. As I just realised I posted the wrong code for the method onCreateOptionsMenu. My code snippet was from the SignSearchActitivity. The only real difference is that in the Fragment getActivity() is called before getSystemService is called. So getActivty() returns null. Why does this occassionaly happen within the onCreateOptionsMenu() method of a fragment?

Answer

You forget to call super.onCreateOptionsMenu(..)

@Override public void onCreateOptionsMenu(Menu menu, MenuInflaterinflater){

Log.d(TAG, "onCreateOptionsMenu " + hashCode());

super.onCreateOptionsMenu(menu, inflater);

inflater.inflate(R.menu.options_sign_browser, menu);
final MenuItem item = menu.findItem(R.id.action_toggle_starred);

if (this.showStarredOnly) {
    item.setIcon(R.drawable.ic_sign_browser_grade_checked);
} else {
    item.setIcon(R.drawable.ic_sign_browser_grade);
}

final SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);

final MenuItem searchItem = menu.findItem(R.id.action_search);

final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));

}

Comments