Search code examples
androidnullpointerexceptionsearchview

SearchView After Voice Implemantation throws NullPointerException


I tried to implement Voice Search by following steps here; ActionBar Mic Button(Voice Search) in SearchView

Everything is fine,I've added all necessary info to my AndroidManifest and searcabhle.xml so I'm able to see mic icon and Search Bar,the problem is when I try to search with voice after saying something,it doesn't find anything and app crashes,looks like something wrong with SetQuery and here's the full error;

2019-03-13 04:55:55.723 1533-1533/com.demotxt.myapp.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.demotxt.myapp.myapplication, PID: 1533
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.SearchView.setQuery(java.lang.CharSequence, boolean)' on a null object reference
    at com.demotxt.myapp.myapplication.activities.MainActivity.onNewIntent(MainActivity.java:153)
    at android.app.Instrumentation.callActivityOnNewIntent(Instrumentation.java:1231)
    at android.app.Instrumentation.callActivityOnNewIntent(Instrumentation.java:1243)
    at android.app.ActivityThread.deliverNewIntents(ActivityThread.java:3064)
    at android.app.ActivityThread.performNewIntents(ActivityThread.java:3076)
    at android.app.ActivityThread.handleNewIntent(ActivityThread.java:3085)
    at android.app.ActivityThread.-wrap17(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1710)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6682)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

And this is my Main3Activity;

 private static final String TAG = "Main3Activity";
private final String JSON_URL = "https://MYURLXXX" ;
private JsonArrayRequest request ;
private RequestQueue requestQueue ;
private List<Anime> lstAnime ;
private RecyclerView recyclerView ;
private RecyclerViewLiveAdapter adapter;
RecyclerView.LayoutManager layoutManager;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        lstAnime = new ArrayList<>() ;
        recyclerView = findViewById(R.id.recyclerviewid);
        jsonrequest();



    }

    private void jsonrequest() {

        request = new JsonArrayRequest(JSON_URL, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {

                JSONObject jsonObject  = null ;

                for (int i = 0 ; i < response.length(); i++ ) {


                    try {
                        jsonObject = response.getJSONObject(i) ;
                        Anime anime = new Anime() ;
                        anime.setName(jsonObject.getString("name"));
                        anime.setDescription(jsonObject.getString("description"));
                        anime.setRating(jsonObject.getString("Rating"));
                        anime.setCategorie(jsonObject.getString("categorie"));
                        anime.setStudio(jsonObject.getString("studio"));
                        anime.setImage_url(jsonObject.getString("img"));
                        anime.setLink(jsonObject.getString("link"));
                        anime.setDrm_scheme(jsonObject.getString("drm_scheme"));
                        anime.setDrm_license_url(jsonObject.getString("drm_license_url"));
                        anime.setDrm(jsonObject.getString("drm"));
                        anime.setSubtitle(jsonObject.getString("subtitle"));
                        anime.setSubtitle1(jsonObject.getString("subtitle1"));
                        anime.setSubtitle2(jsonObject.getString("subtitle2"));
                        lstAnime.add(anime);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    setuprecyclerview(lstAnime);


                }


            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });


        requestQueue = Volley.newRequestQueue(Main3Activity.this);
        requestQueue.add(request) ;


    }

    private void setuprecyclerview(List<Anime> lstAnime) {


        adapter = new RecyclerViewLiveAdapter(this,lstAnime) ;
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_item,menu);

        MenuItem searchItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
        {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                if (adapter != null){
                adapter.getFilter().filter(newText);}
                return false;
            }
        });
        return true;

    }

   protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);

            searchView.setQuery(query, false);
        }
    }
}

I do filtering stuff in my adapter but since error happens here, I think there's no need to put my adapter code here and also because filtering with text works perfectly, the only problem is voice search.


Solution

  • That's because you are accessing a null searchView object in onNewIntent(). Create a global reference variable for searchView in your class and instantiate in onCreateOptionsMenu(). Like below:

    SearchView searchView;
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu_item,menu);
    
            MenuItem searchItem = menu.findItem(R.id.action_search);
            searchView = (SearchView) searchItem.getActionView();
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
            {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    return false;
                }
    
                @Override
                public boolean onQueryTextChange(String newText) {
                    if (adapter != null){
                    adapter.getFilter().filter(newText);}
                    return false;
                }
            });
            return true;
    }