put search fragment into own package

This commit is contained in:
Christian Schabesberger 2016-08-02 15:06:02 +02:00
parent c46ce1170c
commit 3a5b9203d8
12 changed files with 493 additions and 161 deletions

View File

@ -1,13 +1,72 @@
package org.schabi.newpipe;
import android.content.Intent;
import android.media.AudioManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import org.schabi.newpipe.extractor.ServiceList;
import java.util.Vector;
/**
* Created by Christian Schabesberger on 02.08.16.
*/
public class MainActivity extends AppCompatActivity {
private Fragment mainFragment = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mainFragment = getSupportFragmentManager()
.findFragmentById(R.id.search_fragment);
}
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
mainFragment.onCreateOptionsMenu(menu, inflater);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id) {
case android.R.id.home: {
Intent intent = new Intent(this, VideoItemListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
}
case R.id.action_settings: {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}
case R.id.action_show_downloads: {
Intent intent = new Intent(this, org.schabi.newpipe.download.MainActivity.class);
startActivity(intent);
return true;
}
default:
return mainFragment.onOptionsItemSelected(item) ||
super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,86 +0,0 @@
package org.schabi.newpipe;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.schabi.newpipe.dummy.DummyContent;
import org.schabi.newpipe.dummy.DummyContent.DummyItem;
import java.util.List;
/**
* A fragment representing a list of Items.
* <p/>
* Activities containing this fragment MUST implement the {@link OnListFragmentInteractionListener}
* interface.
*/
public class SearchInfoItemFragment extends Fragment {
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public SearchInfoItemFragment() {
}
// TODO: Customize parameter initialization
@SuppressWarnings("unused")
public static SearchInfoItemFragment newInstance(int columnCount) {
SearchInfoItemFragment fragment = new SearchInfoItemFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_searchinfoitem, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(null);
}
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
}

View File

@ -9,7 +9,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**

View File

@ -1,72 +0,0 @@
package org.schabi.newpipe.dummy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper class for providing sample content for user interfaces created by
* Android template wizards.
* <p/>
* TODO: Replace all uses of this class before publishing your app.
*/
public class DummyContent {
/**
* An array of sample (dummy) items.
*/
public static final List<DummyItem> ITEMS = new ArrayList<DummyItem>();
/**
* A map of sample (dummy) items, by ID.
*/
public static final Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
private static final int COUNT = 25;
static {
// Add some sample items.
for (int i = 1; i <= COUNT; i++) {
addItem(createDummyItem(i));
}
}
private static void addItem(DummyItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
private static DummyItem createDummyItem(int position) {
return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position));
}
private static String makeDetails(int position) {
StringBuilder builder = new StringBuilder();
builder.append("Details about Item: ").append(position);
for (int i = 0; i < position; i++) {
builder.append("\nMore details information here.");
}
return builder.toString();
}
/**
* A dummy item representing a piece of content.
*/
public static class DummyItem {
public final String id;
public final String content;
public final String details;
public DummyItem(String id, String content, String details) {
this.id = id;
this.content = content;
this.details = details;
}
@Override
public String toString() {
return content;
}
}
}

View File

@ -0,0 +1,224 @@
package org.schabi.newpipe.search_fragment;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.widget.CursorAdapter;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.Toast;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.ServiceList;
import java.io.IOException;
import java.util.List;
/**
* Created by Christian Schabesberger on 02.08.16.
*/
public class SearchInfoItemFragment extends Fragment {
private static final String TAG = SearchInfoItemFragment.class.toString();
public class SearchQueryListener implements SearchView.OnQueryTextListener {
@Override
public boolean onQueryTextSubmit(String query) {
Activity a = getActivity();
try {
searchQuery = query;
search(query);
// hide virtual keyboard
InputMethodManager inputManager =
(InputMethodManager) a.getSystemService(Context.INPUT_METHOD_SERVICE);
try {
//noinspection ConstantConditions
inputManager.hideSoftInputFromWindow(
a.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
} catch(NullPointerException e) {
e.printStackTrace();
ErrorActivity.reportError(a, e, null,
a.findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
ServiceList.getNameOfService(streamingServiceId),
"Could not get widget with focus", R.string.general_error));
}
// clear focus
// 1. to not open up the keyboard after switching back to this
// 2. It's a workaround to a seeming bug by the Android OS it self, causing
// onQueryTextSubmit to trigger twice when focus is not cleared.
// See: http://stackoverflow.com/questions/17874951/searchview-onquerytextsubmit-runs-twice-while-i-pressed-once
a.getCurrentFocus().clearFocus();
} catch(Exception e) {
e.printStackTrace();
}
View bg = a.findViewById(R.id.mainBG);
bg.setVisibility(View.GONE);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
if(!newText.isEmpty()) {
searchSuggestions(newText);
}
return true;
}
}
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
private int streamingServiceId = -1;
private String searchQuery = "";
private SearchView searchView = null;
private SuggestionListAdapter suggestionListAdapter = null;
// savedInstanceBundle arguments
private static final String QUERY = "query";
private static final String STREAMING_SERVICE = "streaming_service";
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public SearchInfoItemFragment() {
}
// TODO: Customize parameter initialization
@SuppressWarnings("unused")
public static SearchInfoItemFragment newInstance(int columnCount) {
SearchInfoItemFragment fragment = new SearchInfoItemFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
if(savedInstanceState != null) {
searchQuery = savedInstanceState.getString(QUERY);
streamingServiceId = savedInstanceState.getInt(STREAMING_SERVICE);
} else {
try {
streamingServiceId = ServiceList.getIdOfService("Youtube");
} catch(Exception e) {
e.printStackTrace();
ErrorActivity.reportError(getActivity(), e, null,
getActivity().findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
ServiceList.getNameOfService(streamingServiceId),
"", R.string.general_error));
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_searchinfoitem, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(null);
}
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) searchItem.getActionView();
setupSearchView(searchView);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
private void setupSearchView(SearchView searchView) {
suggestionListAdapter = new SuggestionListAdapter(getActivity());
searchView.setSuggestionsAdapter(suggestionListAdapter);
searchView.setOnSuggestionListener(new SearchSuggestionListener(searchView, suggestionListAdapter));
searchView.setOnQueryTextListener(new SearchQueryListener());
if(!searchQuery.isEmpty()) {
searchView.setQuery(searchQuery, false);
searchView.setIconifiedByDefault(false);
}
}
private void search(String query) {
}
private void searchSuggestions(String query) {
SuggestionSearchRunnable suggestionSearchRunnable =
new SuggestionSearchRunnable(streamingServiceId, query, getActivity(), suggestionListAdapter);
Thread suggestionThread = new Thread(suggestionSearchRunnable);
suggestionThread.start();
}
private void postNewErrorToast(Handler h, final int stringResource) {
h.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity(), getString(stringResource),
Toast.LENGTH_SHORT).show();
}
});
}
}

View File

@ -0,0 +1,32 @@
package org.schabi.newpipe.search_fragment;
import android.support.v7.widget.SearchView;
/**
* Created by the-scrabi on 02.08.16.
*/
public class SearchSuggestionListener implements SearchView.OnSuggestionListener{
private SearchView searchView;
private SuggestionListAdapter adapter;
public SearchSuggestionListener(SearchView searchView, SuggestionListAdapter adapter) {
this.searchView = searchView;
this.adapter = adapter;
}
@Override
public boolean onSuggestionSelect(int position) {
String suggestion = adapter.getSuggestion(position);
searchView.setQuery(suggestion,true);
return false;
}
@Override
public boolean onSuggestionClick(int position) {
String suggestion = adapter.getSuggestion(position);
searchView.setQuery(suggestion,true);
return false;
}
}

View File

@ -0,0 +1,66 @@
package org.schabi.newpipe.search_fragment;
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.List;
/**
* Created by the-scrabi on 02.08.16.
*/
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(List<String> 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;
}
}

View File

@ -0,0 +1,90 @@
package org.schabi.newpipe.search_fragment;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.widget.Toast;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.ServiceList;
import java.io.IOException;
import java.util.List;
/**
* Created by the-scrabi on 02.08.16.
*/
public class SuggestionSearchRunnable implements Runnable{
private class SuggestionResultRunnable implements Runnable{
private List<String> suggestions;
private SuggestionListAdapter adapter;
private SuggestionResultRunnable(List<String> suggestions, SuggestionListAdapter adapter) {
this.suggestions = suggestions;
this.adapter = adapter;
}
@Override
public void run() {
adapter.updateAdapter(suggestions);
}
}
private final int serviceId;
private final String query;
final Handler h = new Handler();
private Activity a = null;
private SuggestionListAdapter adapter;
public SuggestionSearchRunnable(int serviceId, String query,
Activity activity, SuggestionListAdapter adapter) {
this.serviceId = serviceId;
this.query = query;
this.a = activity;
this.adapter = adapter;
}
@Override
public void run() {
try {
SearchEngine engine =
ServiceList.getService(serviceId).getSearchEngineInstance(new Downloader());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(a);
String searchLanguageKey = a.getString(R.string.search_language_key);
String searchLanguage = sp.getString(searchLanguageKey,
a.getString(R.string.default_language_value));
List<String> suggestions = engine.suggestionList(query,searchLanguage,new Downloader());
h.post(new SuggestionResultRunnable(suggestions, adapter));
} catch (ExtractionException e) {
ErrorActivity.reportError(h, a, e, null, a.findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
ServiceList.getNameOfService(serviceId), query, R.string.parsing_error));
e.printStackTrace();
} catch (IOException e) {
postNewErrorToast(h, R.string.network_error);
e.printStackTrace();
} catch (Exception e) {
ErrorActivity.reportError(h, a, e, null, a.findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
ServiceList.getNameOfService(serviceId), query, R.string.general_error));
}
}
private void postNewErrorToast(Handler h, final int stringResource) {
h.post(new Runnable() {
@Override
public void run() {
Toast.makeText(a, a.getString(stringResource),
Toast.LENGTH_SHORT).show();
}
});
}
}

View File

@ -10,7 +10,7 @@
<fragment
android:id="@+id/search_fragment"
android:name="org.schabi.newpipe.SearchInfoItemFragment"
android:name="org.schabi.newpipe.search_fragment.SearchInfoItemFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -9,5 +9,5 @@
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="org.schabi.newpipe.SearchInfoItemFragment"
tools:context=".search_fragment.SearchInfoItemFragment"
tools:listitem="@layout/video_item" />

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_settings"
app:showAsAction="never"
android:title="@string/settings"/>
<item android:id="@+id/action_show_downloads"
app:showAsAction="never"
android:title="@string/downloads" />
</menu>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="ifRoom"
android:title="@string/search"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>