/* * TV-Browser for Android * Copyright (C) 2013 René Mach (rene@tvbrowser.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to use, copy, modify or merge the Software, * furthermore to publish and distribute the Software free of charge without modifications and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.tvbrowser.tvbrowser; import org.tvbrowser.content.TvBrowserContentProvider; import org.tvbrowser.devplugin.PluginHandler; import org.tvbrowser.settings.SettingConstants; import org.tvbrowser.utils.PrefUtils; import org.tvbrowser.utils.ProgramUtils; import org.tvbrowser.utils.UiUtils; import org.tvbrowser.view.SeparatorDrawable; import android.app.SearchManager; import android.content.ContentUris; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.Configuration; import android.content.res.Resources.Theme; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; public class ActivityTvBrowserSearchResults extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>, OnSharedPreferenceChangeListener, ShowDateInterface, MarkingsUpdateListener { private SimpleCursorAdapter mProgramsListAdapter; private static String QUERY_EXTRA_KEY = "QUERY_EXTRA_KEY"; private static String QUERY_EXTRA_ID_KEY = "QUERY_EXTRA_ID_KEY"; public static String QUERY_EXTRA_EPISODE_KEY = "QUERY_EXTRA_EPISODE_KEY"; private ProgramListViewBinderAndClickHandler mViewAndClickHandler; private ListView mListView; private Handler mHandler; private String mSearchString; private String mEpisodeString; @Override protected void onApplyThemeResource(Theme theme, int resid, boolean first) { PrefUtils.initialize(ActivityTvBrowserSearchResults.this); if(PrefUtils.getBooleanValue(R.string.DARK_STYLE, R.bool.dark_style_default)) { resid = R.style.AppDarkTheme; } else { resid = R.style.AppTheme; } super.onApplyThemeResource(theme, resid, first); } private ListView getListView() { return mListView; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PrefUtils.initialize(ActivityTvBrowserSearchResults.this); SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ActivityTvBrowserSearchResults.this); pref.registerOnSharedPreferenceChangeListener(this); setContentView(R.layout.list_view); mListView = (ListView)findViewById(R.id.list_view); String[] projection = { TvBrowserContentProvider.DATA_KEY_UNIX_DATE, TvBrowserContentProvider.DATA_KEY_STARTTIME, TvBrowserContentProvider.DATA_KEY_ENDTIME, TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID, TvBrowserContentProvider.DATA_KEY_TITLE, TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE, TvBrowserContentProvider.DATA_KEY_GENRE, TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT, TvBrowserContentProvider.DATA_KEY_CATEGORIES }; registerForContextMenu(getListView()); // Create a new Adapter an bind it to the List View mHandler = new Handler(); mViewAndClickHandler = new ProgramListViewBinderAndClickHandler(this,this,mHandler); mProgramsListAdapter = new OrientationHandlingCursorAdapter(this,/*android.R.layout.simple_list_item_1*/R.layout.program_lists_entries,null, projection,new int[] {R.id.startDateLabelPL,R.id.startTimeLabelPL,R.id.endTimeLabelPL,R.id.channelLabelPL,R.id.titleLabelPL,R.id.episodeLabelPL,R.id.genre_label_pl,R.id.picture_copyright_pl,R.id.info_label_pl},0,false,mHandler); mProgramsListAdapter.setViewBinder(mViewAndClickHandler); getListView().setAdapter(mProgramsListAdapter); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> l, View v, int position, long id) { mViewAndClickHandler.onListItemClick((ListView)l, v, position, id); } }); // Initiate the Cursor Loader getSupportLoaderManager().initLoader(0, null, this); // Get the launch Intent parseIntent(getIntent()); SeparatorDrawable drawable = new SeparatorDrawable(this); getListView().setDivider(drawable); setDividerSize(PrefUtils.getStringValue(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE, R.string.pref_program_lists_divider_size_default)); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { long programID = ((AdapterView.AdapterContextMenuInfo)menuInfo).id; UiUtils.createContextMenu(ActivityTvBrowserSearchResults.this, menu, programID); } @Override protected void onResume() { PluginHandler.incrementBlogCount(); ProgramUtils.registerMarkingsListener(getApplicationContext(), this); super.onResume(); } @Override protected void onPause() { PluginHandler.decrementBlogCount(); ProgramUtils.unregisterMarkingsListener(getApplicationContext(), this); super.onPause(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); parseIntent(getIntent()); } private void parseIntent(Intent intent) { // If the Activity was started to service a Search request, extract the search query. if (Intent.ACTION_SEARCH.equals(intent.getAction())) { mSearchString = intent.getStringExtra(SearchManager.QUERY); // Perfom the search, passing in the search query as an argument to the Cursor Loader Bundle args = new Bundle(); args.putString(QUERY_EXTRA_KEY, mSearchString); if(intent.hasExtra(QUERY_EXTRA_EPISODE_KEY)) { mEpisodeString = intent.getStringExtra(QUERY_EXTRA_EPISODE_KEY); args.putString(QUERY_EXTRA_EPISODE_KEY, mEpisodeString); } // Restart the Cursor Loader to execute the new query getSupportLoaderManager().restartLoader(0, args, this); } else if(Intent.ACTION_VIEW.equals(intent.getAction())) { try { long key = Long.parseLong(intent.getData().getPathSegments().get(1)); Bundle args = new Bundle(); args.putLong(QUERY_EXTRA_ID_KEY, key); getSupportLoaderManager().restartLoader(0, args, this); }catch(NumberFormatException e) { // Ignore } } else if(intent.hasExtra(SearchManager.QUERY)) { Bundle args = new Bundle(); mSearchString = intent.getStringExtra(SearchManager.QUERY); args.putString(QUERY_EXTRA_KEY, mSearchString); if(intent.hasExtra(QUERY_EXTRA_EPISODE_KEY)) { mEpisodeString = intent.getStringExtra(QUERY_EXTRA_EPISODE_KEY); args.putString(QUERY_EXTRA_EPISODE_KEY, mEpisodeString); } // Restart the Cursor Loader to execute the new query getSupportLoaderManager().restartLoader(0, args, this); } } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { String query = "0"; String episodeQuery = "0"; String operation = " OR "; long ID = -1; if(args != null) { // Extract the search query from the arguments. if(args.containsKey(QUERY_EXTRA_KEY)) { episodeQuery = query = args.getString(QUERY_EXTRA_KEY); } ID = args.getLong(QUERY_EXTRA_ID_KEY, -1); if(args.containsKey(QUERY_EXTRA_EPISODE_KEY)) { episodeQuery = args.getString(QUERY_EXTRA_EPISODE_KEY); operation = " AND "; } } // Construct the new query in form of a Cursor Loader String[] projection = null; if(PrefUtils.getBooleanValue(R.string.SHOW_PICTURE_IN_LISTS, R.bool.show_pictures_in_lists_default)) { projection = new String[14 + TvBrowserContentProvider.MARKING_COLUMNS.length]; projection[projection.length-1] = TvBrowserContentProvider.DATA_KEY_PICTURE; } else { projection = new String[13 + TvBrowserContentProvider.MARKING_COLUMNS.length]; } projection[0] = TvBrowserContentProvider.KEY_ID; projection[1] = TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID; projection[2] = TvBrowserContentProvider.DATA_KEY_STARTTIME; projection[3] = TvBrowserContentProvider.DATA_KEY_ENDTIME; projection[4] = TvBrowserContentProvider.DATA_KEY_TITLE; projection[5] = TvBrowserContentProvider.DATA_KEY_SHORT_DESCRIPTION; projection[6] = TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER; projection[7] = TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE; projection[8] = TvBrowserContentProvider.DATA_KEY_GENRE; projection[9] = TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT; projection[10] = TvBrowserContentProvider.DATA_KEY_UNIX_DATE; projection[11] = TvBrowserContentProvider.CHANNEL_KEY_NAME; projection[12] = TvBrowserContentProvider.DATA_KEY_CATEGORIES; System.arraycopy(TvBrowserContentProvider.MARKING_COLUMNS, 0, projection, 13, TvBrowserContentProvider.MARKING_COLUMNS.length); String where = "(" + TvBrowserContentProvider.DATA_KEY_TITLE + " LIKE '%" + query.replace("'", "''") + "%' " + operation + TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE + " LIKE '%" + episodeQuery.replace("'", "''") + "%') AND " + TvBrowserContentProvider.DATA_KEY_ENDTIME + ">=" + System.currentTimeMillis(); String[] whereArgs = null; String sortOrder = TvBrowserContentProvider.DATA_KEY_STARTTIME; Uri uri = TvBrowserContentProvider.CONTENT_URI_DATA_WITH_CHANNEL; if(ID != -1) { where = null; uri = ContentUris.withAppendedId(uri, ID); } else { where += UiUtils.getDontWantToSeeFilterString(ActivityTvBrowserSearchResults.this); } // Create the new Cursor loader return new CursorLoader(this, uri, projection, where, whereArgs, sortOrder); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { mProgramsListAdapter.swapCursor(cursor); if(cursor == null || cursor.getCount() < 1) { AlertDialog.Builder info = new AlertDialog.Builder(ActivityTvBrowserSearchResults.this); info.setTitle(R.string.search_no_result_title); info.setMessage(R.string.search_no_result_text); info.setPositiveButton(R.string.dialog_search_create_favorite, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mHandler.post(new Runnable() { @Override public void run() { UiUtils.editFavorite(null, getApplicationContext(), mSearchString + (mEpisodeString != null ? " AND " + mEpisodeString : "")); } }); finish(); } }); info.setNegativeButton(R.string.dialog_close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); info.show(); } } @Override public void onLoaderReset(Loader<Cursor> loader) { mProgramsListAdapter.swapCursor(null); } @Override public boolean onContextItemSelected(MenuItem item) { return mViewAndClickHandler.onContextItemSelected(item); } /* public void onListItemClick(ListView l, View v, int position, long id) { //super.onListItemClick(l, v, position, id); mViewAndClickHandler.onListItemClick(l, v, position, id); }*/ private void setDividerSize(String size) { getListView().setDividerHeight(UiUtils.convertDpToPixel(Integer.parseInt(size), getResources())); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if(getString(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE).equals(key)) { setDividerSize(PrefUtils.getStringValue(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE, R.string.pref_program_lists_divider_size_default)); } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); SettingConstants.ORIENTATION = newConfig.orientation; //UiUtils.handleConfigurationChange(new Handler(), mProgramsListAdapter, newConfig); } @Override public boolean showDate() { return true; } @Override public void refreshMarkings() { mHandler.post(new Runnable() { @Override public void run() { getListView().invalidateViews(); } }); } }