diff --git a/app/src/androidTest/java/org/schabi/newpipe/extractor/youtube/YoutubeSearchEngineTest.java b/app/src/androidTest/java/org/schabi/newpipe/extractor/youtube/YoutubeSearchEngineTest.java index 7ab6cacf3..ea52539fb 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/extractor/youtube/YoutubeSearchEngineTest.java +++ b/app/src/androidTest/java/org/schabi/newpipe/extractor/youtube/YoutubeSearchEngineTest.java @@ -40,7 +40,7 @@ public class YoutubeSearchEngineTest extends AndroidTestCase { result = engine.search("https://www.youtube.com/results?search_query=bla", 0, "de", new Downloader()); - suggestionReply = engine.suggestionList("hello", new Downloader()); + suggestionReply = engine.suggestionList("hello","de",new Downloader()); } public void testIfNoErrorOccur() { diff --git a/app/src/main/java/org/schabi/newpipe/SuggestionListAdapter.java b/app/src/main/java/org/schabi/newpipe/SuggestionListAdapter.java new file mode 100644 index 000000000..53e824c78 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/SuggestionListAdapter.java @@ -0,0 +1,65 @@ +package org.schabi.newpipe; + +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.support.v4.widget.CursorAdapter; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * Created by Madiyar on 23.02.2016. + */ +public class SuggestionListAdapter extends CursorAdapter { + + private String[] columns = new String[]{"_id", "title"}; + + public SuggestionListAdapter(Context context) { + super(context, null, false); + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + ViewHolder viewHolder; + + View view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false); + viewHolder = new ViewHolder(); + viewHolder.suggestionTitle = (TextView) view.findViewById(android.R.id.text1); + view.setTag(viewHolder); + + + return view; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ViewHolder viewHolder = (ViewHolder) view.getTag(); + viewHolder.suggestionTitle.setText(cursor.getString(1)); + } + + + public void updateAdapter(ArrayList suggestions) { + MatrixCursor cursor = new MatrixCursor(columns); + int i = 0; + for (String s : suggestions) { + String[] temp = new String[2]; + temp[0] = Integer.toString(i); + temp[1] = s; + i++; + cursor.addRow(temp); + } + changeCursor(cursor); + } + + public String getSuggestion(int position) { + return ((Cursor) getItem(position)).getString(1); + } + + private class ViewHolder { + public TextView suggestionTitle; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java index f6c8938a8..5f04d5174 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java @@ -2,7 +2,9 @@ package org.schabi.newpipe; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.NavUtils; import android.support.v7.app.AppCompatActivity; @@ -13,11 +15,16 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; -import java.util.ArrayList; - -import org.schabi.newpipe.extractor.VideoPreviewInfo; +import org.schabi.newpipe.extractor.ExtractionException; +import org.schabi.newpipe.extractor.SearchEngine; import org.schabi.newpipe.extractor.ServiceList; +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.VideoPreviewInfo; + +import java.io.IOException; +import java.util.ArrayList; /** * Copyright (C) Christian Schabesberger 2015 @@ -61,6 +68,11 @@ public class VideoItemListActivity extends AppCompatActivity private VideoItemDetailFragment videoFragment = null; private Menu menu = null; + private SuggestionListAdapter suggestionListAdapter; + private StreamingService streamingService; + private SuggestionSearchRunnable suggestionSearchRunnable; + private Thread searchThread; + private class SearchVideoQueryListener implements SearchView.OnQueryTextListener { @Override @@ -78,6 +90,8 @@ public class VideoItemListActivity extends AppCompatActivity getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } catch(NullPointerException e) { Log.e(TAG, "Could not get widget with focus"); + Toast.makeText(VideoItemListActivity.this, "Could not get widget with focus", + Toast.LENGTH_SHORT).show(); e.printStackTrace(); } // clear focus @@ -94,11 +108,77 @@ public class VideoItemListActivity extends AppCompatActivity @Override public boolean onQueryTextChange(String newText) { + searchSuggestions(newText); return true; } } + private class SearchSuggestionListener implements SearchView.OnSuggestionListener{ + private SearchView searchView; + + private SearchSuggestionListener(SearchView searchView) { + this.searchView = searchView; + } + + @Override + public boolean onSuggestionSelect(int position) { + String suggestion = suggestionListAdapter.getSuggestion(position); + searchView.setQuery(suggestion,true); + return false; + } + + @Override + public boolean onSuggestionClick(int position) { + String suggestion = suggestionListAdapter.getSuggestion(position); + searchView.setQuery(suggestion,true); + return false; + } + } + + private class SuggestionResultRunnable implements Runnable{ + + private ArrayListsuggestions; + + private SuggestionResultRunnable(ArrayList suggestions) { + this.suggestions = suggestions; + } + + @Override + public void run() { + suggestionListAdapter.updateAdapter(suggestions); + } + } + + private class SuggestionSearchRunnable implements Runnable{ + private final SearchEngine engine; + private final String query; + final Handler h = new Handler(); + private Context context; + private SuggestionSearchRunnable(SearchEngine engine, String query) { + this.engine = engine; + this.query = query; + context = VideoItemListActivity.this; + } + + @Override + public void run() { + try { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + String searchLanguageKey = context.getString(R.string.search_language_key); + String searchLanguage = sp.getString(searchLanguageKey, + getString(R.string.default_language_value)); + ArrayListsuggestions = engine.suggestionList(query,searchLanguage,new Downloader()); + h.post(new SuggestionResultRunnable(suggestions)); + } catch (ExtractionException e) { + postNewErrorToast(h, R.string.parsing_error); + e.printStackTrace(); + } catch (IOException e) { + postNewErrorToast(h, R.string.network_error); + e.printStackTrace(); + } + } + } /** * Whether or not the activity is in two-pane mode, i.e. running on a tablet * device. @@ -112,11 +192,12 @@ public class VideoItemListActivity extends AppCompatActivity //------ todo: remove this line when multiservice support is implemented ------ currentStreamingServiceId = ServiceList.getIdOfService("Youtube"); + streamingService=ServiceList.getService(currentStreamingServiceId); //----------------------------------------------------------------------------- //to solve issue 38 listFragment = (VideoItemListFragment) getSupportFragmentManager() .findFragmentById(R.id.videoitem_list); - listFragment.setStreamingService(ServiceList.getService(currentStreamingServiceId)); + listFragment.setStreamingService(streamingService); Bundle arguments = getIntent().getExtras(); @@ -168,6 +249,9 @@ public class VideoItemListActivity extends AppCompatActivity searchView.setIconifiedByDefault(false); searchView.setIconified(false); searchView.setOnQueryTextListener(new SearchVideoQueryListener()); + suggestionListAdapter = new SuggestionListAdapter(this); + searchView.setSuggestionsAdapter(suggestionListAdapter); + searchView.setOnSuggestionListener(new SearchSuggestionListener(searchView)); } else { searchView.setVisibility(View.GONE); } @@ -237,6 +321,9 @@ public class VideoItemListActivity extends AppCompatActivity searchView.setFocusable(false); searchView.setOnQueryTextListener( new SearchVideoQueryListener()); + suggestionListAdapter = new SuggestionListAdapter(this); + searchView.setSuggestionsAdapter(suggestionListAdapter); + searchView.setOnSuggestionListener(new SearchSuggestionListener(searchView)); } else if (videoFragment != null){ videoFragment.onCreateOptionsMenu(menu, inflater); @@ -281,4 +368,22 @@ public class VideoItemListActivity extends AppCompatActivity outState.putString(QUERY, searchQuery); outState.putInt(STREAMING_SERVICE, currentStreamingServiceId); } + + private void searchSuggestions(String query) { + suggestionSearchRunnable = new SuggestionSearchRunnable(streamingService.getSearchEngineInstance(), + query); + searchThread = new Thread(suggestionSearchRunnable); + searchThread.start(); + + } + + private void postNewErrorToast(Handler h, final int stringResource) { + h.post(new Runnable() { + @Override + public void run() { + Toast.makeText(VideoItemListActivity.this, getString(stringResource), + Toast.LENGTH_SHORT).show(); + } + }); + } } diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java index 999f6875b..e6a6a5060 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java @@ -186,8 +186,12 @@ public class VideoItemListFragment extends ListFragment { videoListAdapter.addVideoList(list); terminateThreads(); } catch(java.lang.IllegalStateException e) { + Toast.makeText(getActivity(), "Trying to set value while activity doesn't exist anymore.", + Toast.LENGTH_SHORT).show(); Log.w(TAG, "Trying to set value while activity doesn't exist anymore."); } catch(Exception e) { + Toast.makeText(getActivity(), getString(R.string.general_error), + Toast.LENGTH_SHORT).show(); e.printStackTrace(); } finally { loadingNextPage = false; diff --git a/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java b/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java index be176d39e..74f3f0f60 100644 --- a/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java +++ b/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java @@ -33,7 +33,7 @@ public interface SearchEngine { public final List resultList = new Vector<>(); } - ArrayList suggestionList(String query, Downloader dl) + ArrayList suggestionList(String query,String contentCountry, Downloader dl) throws ExtractionException, IOException; //Result search(String query, int page); diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java index fd7528926..4f24fb5bd 100644 --- a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java +++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java @@ -147,7 +147,7 @@ public class YoutubeSearchEngine implements SearchEngine { } @Override - public ArrayList suggestionList(String query, Downloader dl) + public ArrayList suggestionList(String query,String contentCountry, Downloader dl) throws IOException, ParsingException { ArrayList suggestions = new ArrayList<>(); @@ -160,6 +160,7 @@ public class YoutubeSearchEngine implements SearchEngine { .appendQueryParameter("client", "") .appendQueryParameter("output", "toolbar") .appendQueryParameter("ds", "yt") + .appendQueryParameter("hl",contentCountry) .appendQueryParameter("q", query); String url = builder.build().toString();