/****************************************************************************** * OpenLP - Open Source Lyrics Projection * * --------------------------------------------------------------------------- * * Copyright (c) 2011-2016 OpenLP Android Developers * * --------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., 59 * * Temple Place, Suite 330, Boston, MA 02111-1307 USA * *******************************************************************************/ package org.openlp.android2.fragments; import android.app.DialogFragment; import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.android.volley.AuthFailureError; import com.android.volley.ClientError; import com.android.volley.DefaultRetryPolicy; import com.android.volley.NetworkError; import com.android.volley.NoConnectionError; import com.android.volley.ParseError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.ServerError; import com.android.volley.TimeoutError; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.openlp.android2.R; import org.openlp.android2.api.Api; import org.openlp.android2.common.JsonHelpers; import org.openlp.android2.common.RequestQueueService; import org.openlp.android2.dialogs.SearchSelectionDialog; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** */ public class SearchFragment extends Fragment { private final String LOG_TAG = SearchFragment.class.getName(); private Spinner spinner; public Context context; protected String calledURL; protected String updateUrl; protected String searchedPlugin; protected Map pluginMap = new HashMap(); public SearchFragment() { Log.d(LOG_TAG, "Constructor"); } public static SearchFragment newInstance() { SearchFragment fragment = new SearchFragment(); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { context = getActivity(); updateUrl = Api.SEARCHABLE_PLUGINS; View view = inflater.inflate(R.layout.fragment_search, container, false); spinner = (Spinner) view.findViewById(R.id.search_spinner); triggerTextRequest(Api.SEARCHABLE_PLUGINS); // Add search listener to text field final EditText editText = (EditText) view.findViewById(R.id.search_text); editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView tv, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { // Now close the keyboard as finished with View view = getActivity().getCurrentFocus(); if (view != null) { InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } searchedPlugin = pluginMap.get(spinner.getSelectedItem().toString()); requestSearch(tv.getText().toString()); return true; } return false; } }); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { /** * Called when a new item is selected (in the Spinner) */ public void onItemSelected(AdapterView parent, View view, int pos, long id) { editText.setText(""); } public void onNothingSelected(AdapterView parent) { // Do nothing, just another required interface callback } }); return view; } @Override public void onDetach() { super.onDetach(); } private void populatePluginList(String response, Boolean notInError) { Log.i(LOG_TAG, "populatePluginList - entry"); List categories = new ArrayList(); pluginMap.clear(); if (notInError) { try { JSONArray items = new JSONObject(response).getJSONObject("results").getJSONArray("items"); for (int i = 0; i < items.length(); ++i) { JSONArray item = items.getJSONArray(i); categories.add(item.get(1).toString()); pluginMap.put(item.get(1).toString(), item.get(0).toString()); } } catch (JSONException e) { Log.e(LOG_TAG, response); e.printStackTrace(); } ArrayAdapter LTRadapter = new ArrayAdapter(getActivity(), R.layout.spinner_list_item, categories); LTRadapter.setDropDownViewResource(R.layout.spinner_dropdown_item); spinner.setAdapter(LTRadapter); Log.i(LOG_TAG, "populatePluginList - exit"); } } protected void triggerTextRequest(String urlbase) { Log.d(LOG_TAG, "Trigger Request for url " + urlbase); String url = RequestQueueService.getInstance(this.context).getUrl(urlbase); calledURL = urlbase; StringRequest request = new StringRequest( Request.Method.GET, url, listener, errorListener) { @Override public Map getHeaders() throws AuthFailureError { return createBasicAuthHeader("user", "passwd"); } }; //Set a retry policy in case of SocketTimeout & ConnectionTimeout Exceptions. // Volley does retry for you if you have specified the policy. request.setRetryPolicy(new DefaultRetryPolicy( RequestQueueService.getInstance(this.context).getConnectionTimeout(), DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); request.setTag("OpenLP"); RequestQueueService.getInstance(this.context).addToRequestQueue(request); } Map createBasicAuthHeader(String username, String password) { Map headers = new HashMap(); headers.put("Authorization", RequestQueueService.getInstance(context).getBasicAuth()); return headers; } Response.Listener listener = new Response.Listener() { @Override public void onResponse(String response) { if (calledURL.equals(updateUrl)) { populatePluginList(response, true); } else { populateListDisplay(response, true); } } }; Response.ErrorListener errorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d(LOG_TAG, String.format("Call response error = %s", error.toString())); if (error instanceof NetworkError) { } else if (error instanceof ClientError) { } else if (error instanceof ServerError) { } else if (error instanceof AuthFailureError) { Toast.makeText(context, R.string.httpreturn_unauthorised, Toast.LENGTH_LONG).show(); } else if (error instanceof ParseError) { } else if (error instanceof NoConnectionError) { } else if (error instanceof TimeoutError) { } Toast.makeText(context, R.string.unable, Toast.LENGTH_LONG).show(); } }; public void requestSearch(String text) { updateUrl = Api.SEARCH_PLUGIN_FORMATTED; try { String request = JsonHelpers.createRequestJSON("text", text); String url = String.format(Api.SEARCH_PLUGIN_FORMATTED, searchedPlugin); triggerTextRequest(String.format("%s%s", url, request)); Log.d(LOG_TAG, String.format("Search request. apiBase(%s), text(%s)", searchedPlugin, text)); } catch (JsonHelpers.JSONHandlerException e) { e.printStackTrace(); Toast.makeText(context, "Search Request Failed", Toast.LENGTH_SHORT).show(); } } public void populateListDisplay(String json, boolean notInError) { Log.i(LOG_TAG, "populateListDisplay - entry"); ListView list = (ListView) getActivity().findViewById(R.id.searchListView); final ArrayList listitems = new ArrayList(); if (notInError) { try { JSONArray items = new JSONObject(json).getJSONObject("results").getJSONArray("items"); Log.d(LOG_TAG,items.toString()); for (int i = 0; i < items.length(); ++i) { JSONArray item = items.getJSONArray(i); listitems.add(item); } } catch (JSONException e) { Log.e(LOG_TAG, json); e.printStackTrace(); } } final StableArrayAdapter adapter = new StableArrayAdapter(context, android.R.layout.simple_list_item_1, listitems); list.setAdapter(adapter); list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, final View view, int position, long id) { final JSONArray item = (JSONArray) parent.getItemAtPosition(position); //Toast.makeText(context, "Item Pressed " + String.valueOf(position) + item, // Toast.LENGTH_SHORT).show(); String it = ""; try { Log.i(LOG_TAG, "list.setOnItemClickListener" + item); it = item.get(0).toString(); } catch (JSONException e) { e.printStackTrace(); } Bundle args = new Bundle(); args.putString("plugin", searchedPlugin); args.putString("text", it); args.putString("key", Long.toString(id)); DialogFragment SSDFragment = new SearchSelectionDialog(); SSDFragment.setArguments(args); SSDFragment.show(getFragmentManager(), "TAG"); } }); Log.i(LOG_TAG, "populateListDisplay - exit"); } public class StableArrayAdapter extends ArrayAdapter { HashMap mIdMap = new HashMap(); public StableArrayAdapter(Context context, int textViewResourceId, List objects) { super(context, textViewResourceId, objects); for (int i = 0; i < objects.size(); ++i) { JSONArray item = objects.get(i); try { mIdMap.put(item.get(1).toString(), i); } catch (JSONException e) { e.printStackTrace(); } } } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get the data item for this position //User user = getItem(position); String item = null; try { item = getItem(position).get(1).toString(); } catch (JSONException e) { e.printStackTrace(); } // Check if an existing view is being reused, otherwise inflate the view if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.search_result_row, parent, false); } // Lookup view for data population TextView tvItem = (TextView) convertView.findViewById(R.id.searchListRow); // Populate the data into the template view using the data object tvItem.setText(item); // Return the completed view to render on screen return convertView; } @Override public long getItemId(int position) { String item = null; try { item = getItem(position).get(1).toString(); } catch (JSONException e) { e.printStackTrace(); } return mIdMap.get(item); } @Override public boolean hasStableIds() { return true; } } }