3

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?

Matthias T
  • 1,230
  • 2
  • 10
  • 24
  • 1
    Voting to reopen, as he was explicit in what was returning null and wanted to know why it was happening, rather than being a generic null pointer question – Gabe Sechan Jun 08 '16 at 20:59
  • Your stack trace shows that you are calling `getSystemService()` on an `Activity`. Your code shows that you are calling `getSystemService()` in a fragment. The only way that this would compile would be if your fragment is a nested (non-`static`) class inside your activity, and that is not going to work. – CommonsWare Jun 08 '16 at 21:05
  • You're right, just realised that I posted the wrong code. Updated the question. – Matthias T Jun 08 '16 at 21:11
  • Maybe the fragment becomes detached from the Activity when the option menu is displayed? You could try to surround that code with `if (isAdded())` – OneCricketeer Jun 08 '16 at 21:24
  • Try `getContext().getSystemService()`. – Shadab Ansari Jun 08 '16 at 21:44
  • Can't use getContext() as I'm on minimum API level 15. – Matthias T Jun 08 '16 at 22:28

3 Answers3

0

The problem is with

searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

What if the object is null (means the getSystemService(Context.SEARCH_SERVICE); returned a null object)? it will throw NPE, right.

Change your code to:

 if(searchManager != null){
      searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    }
else{
     // Can't perform the search because of null object message to the user (or) log (or) console.
    }
K139
  • 3,654
  • 13
  • 17
  • Thanks for the answer. Just realised that I posted the wrong code snippet, though. Please see the updated question. Thanks. – Matthias T Jun 08 '16 at 21:14
0

i think you are facing this error because you are calling the activity from fragment even if it's not created. You should call the getActivity() only after or during the execution onActivityCreated() function of fragment which notifies that activity is created. OnCreateOptionsMenu() is called from the onCreate() method so it is possible that your activity is not created at that point of time. see this link for more info https://developer.android.com/guide/components/fragments.html

hiten pannu
  • 186
  • 1
  • 6
-1

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()));

}

Community
  • 1
  • 1
HocineHamdi
  • 191
  • 6
  • Hi, thanks for the reply. I can't really reproduce my NPE right now as it only occurs occasionally, however adding the call to the super method does not seem to hurt either. The JavaDoc of onCreateOptionsMenu() of the Activity also states: "Deriving classes should always call through to the base implementation." So for fragments this should also be true. Accepting this as the correct answer. Will re-open if the bug occurs again. – Matthias T Jun 08 '16 at 22:31
  • I already call the super. This does nothing to mitigate the issue. – Shroud Aug 30 '17 at 15:53