Home | History | Annotate | Download | only in search
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tv.search;
     18 
     19 import android.content.res.Resources;
     20 import android.graphics.Bitmap;
     21 import android.graphics.drawable.BitmapDrawable;
     22 import android.os.AsyncTask;
     23 import android.os.Bundle;
     24 import android.support.v17.leanback.app.SearchFragment;
     25 import android.support.v17.leanback.widget.ArrayObjectAdapter;
     26 import android.support.v17.leanback.widget.HeaderItem;
     27 import android.support.v17.leanback.widget.ImageCardView;
     28 import android.support.v17.leanback.widget.ListRow;
     29 import android.support.v17.leanback.widget.ListRowPresenter;
     30 import android.support.v17.leanback.widget.ObjectAdapter;
     31 import android.support.v17.leanback.widget.OnItemViewClickedListener;
     32 import android.support.v17.leanback.widget.Presenter;
     33 import android.support.v17.leanback.widget.Row;
     34 import android.support.v17.leanback.widget.RowPresenter;
     35 import android.support.v17.leanback.widget.SearchBar;
     36 import android.text.TextUtils;
     37 import android.util.Log;
     38 import android.view.LayoutInflater;
     39 import android.view.View;
     40 import android.view.ViewGroup;
     41 
     42 import com.android.tv.MainActivity;
     43 import com.android.tv.R;
     44 import com.android.tv.util.ImageLoader;
     45 import com.android.tv.util.PermissionUtils;
     46 
     47 import java.util.List;
     48 
     49 public class ProgramGuideSearchFragment extends SearchFragment {
     50     private static final String TAG = "ProgramGuideSearch";
     51     private static final boolean DEBUG = false;
     52     private static final int SEARCH_RESULT_MAX = 10;
     53 
     54     private final Presenter mPresenter = new Presenter() {
     55         @Override
     56         public Presenter.ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
     57             if (DEBUG) Log.d(TAG, "onCreateViewHolder");
     58 
     59             ImageCardView cardView = new ImageCardView(mMainActivity);
     60             cardView.setFocusable(true);
     61             cardView.setFocusableInTouchMode(true);
     62             cardView.setMainImageAdjustViewBounds(false);
     63 
     64             Resources res = mMainActivity.getResources();
     65             cardView.setMainImageDimensions(
     66                     res.getDimensionPixelSize(R.dimen.card_image_layout_width),
     67                     res.getDimensionPixelSize(R.dimen.card_image_layout_height));
     68 
     69             return new Presenter.ViewHolder(cardView);
     70         }
     71 
     72         @Override
     73         public void onBindViewHolder(ViewHolder viewHolder, Object o) {
     74             ImageCardView cardView = (ImageCardView) viewHolder.view;
     75             LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
     76             if (DEBUG) Log.d(TAG, "onBindViewHolder result:" + result);
     77 
     78             cardView.setTitleText(result.title);
     79             if (!TextUtils.isEmpty(result.imageUri)) {
     80                 ImageLoader.loadBitmap(mMainActivity, result.imageUri, mMainCardWidth,
     81                         mMainCardHeight, createImageLoaderCallback(cardView));
     82             } else {
     83                 cardView.setMainImage(mMainActivity.getDrawable(R.drawable.ic_launcher));
     84             }
     85         }
     86 
     87         @Override
     88         public void onUnbindViewHolder(ViewHolder viewHolder) {
     89             // Do nothing here.
     90         }
     91     };
     92 
     93     private static ImageLoader.ImageLoaderCallback<ImageCardView> createImageLoaderCallback(
     94             ImageCardView cardView) {
     95         return new ImageLoader.ImageLoaderCallback<ImageCardView>(cardView) {
     96             @Override
     97             public void onBitmapLoaded(ImageCardView cardView, Bitmap bitmap) {
     98                 cardView.setMainImage(
     99                         new BitmapDrawable(cardView.getContext().getResources(), bitmap));
    100             }
    101         };
    102     }
    103 
    104     private final SearchResultProvider mSearchResultProvider = new SearchResultProvider() {
    105         @Override
    106         public ObjectAdapter getResultsAdapter() {
    107             return mResultAdapter;
    108         }
    109 
    110         @Override
    111         public boolean onQueryTextChange(String query) {
    112             searchAndRefresh(query);
    113             return true;
    114         }
    115 
    116         @Override
    117         public boolean onQueryTextSubmit(String query) {
    118             searchAndRefresh(query);
    119             return true;
    120         }
    121     };
    122 
    123     private final OnItemViewClickedListener mItemClickedListener = new OnItemViewClickedListener() {
    124         @Override
    125         public void onItemClicked(Presenter.ViewHolder viewHolder, Object o, RowPresenter
    126                 .ViewHolder viewHolder1, Row row) {
    127             LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
    128             mMainActivity.getFragmentManager().popBackStack();
    129             mMainActivity.tuneToChannel(
    130                     mMainActivity.getChannelDataManager().getChannel(result.channelId));
    131         }
    132     };
    133 
    134     private final ArrayObjectAdapter mResultAdapter =
    135             new ArrayObjectAdapter(new ListRowPresenter());
    136     private MainActivity mMainActivity;
    137     private SearchInterface mSearch;
    138     private int mMainCardWidth;
    139     private int mMainCardHeight;
    140     private SearchTask mSearchTask;
    141 
    142     @Override
    143     public void onCreate(Bundle savedInstanceState) {
    144         super.onCreate(savedInstanceState);
    145 
    146         mMainActivity = (MainActivity) getActivity();
    147         if (PermissionUtils.hasAccessAllEpg(mMainActivity)) {
    148             mSearch = new TvProviderSearch(mMainActivity);
    149         } else {
    150             mSearch = new DataManagerSearch(mMainActivity);
    151         }
    152         Resources res = getResources();
    153         mMainCardWidth = res.getDimensionPixelSize(R.dimen.card_image_layout_width);
    154         mMainCardHeight = res.getDimensionPixelSize(R.dimen.card_image_layout_height);
    155     }
    156 
    157     @Override
    158     public View onCreateView(
    159             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    160         View v = super.onCreateView(inflater, container, savedInstanceState);
    161         v.setBackgroundResource(R.color.program_guide_scrim);
    162 
    163         setBadgeDrawable(mMainActivity.getDrawable(R.drawable.ic_launcher));
    164         setSearchResultProvider(mSearchResultProvider);
    165         setOnItemViewClickedListener(mItemClickedListener);
    166         return v;
    167     }
    168 
    169     @Override
    170     public void onResume() {
    171         super.onResume();
    172 
    173         SearchBar searchBar = (SearchBar) getView().findViewById(R.id.lb_search_bar);
    174         searchBar.setSearchQuery("");
    175         mResultAdapter.clear();
    176     }
    177 
    178     private void searchAndRefresh(String query) {
    179         // TODO: Search directly from program data manager for performance.
    180         // TODO: Search upcoming programs.
    181         if (mSearchTask != null) {
    182             mSearchTask.cancel(true);
    183         }
    184         mSearchTask = new SearchTask(query);
    185         mSearchTask.execute();
    186     }
    187 
    188     private class SearchTask extends
    189             AsyncTask<Void, Void, List<LocalSearchProvider.SearchResult>> {
    190         private final String mQuery;
    191 
    192         public SearchTask(String query) {
    193             mQuery = query;
    194         }
    195 
    196         @Override
    197         protected List<LocalSearchProvider.SearchResult> doInBackground(Void... params) {
    198             return mSearch.search(mQuery, SEARCH_RESULT_MAX,
    199                     TvProviderSearch.ACTION_TYPE_AMBIGUOUS);
    200         }
    201 
    202         @Override
    203         protected void onPostExecute(List<LocalSearchProvider.SearchResult> results) {
    204             super.onPostExecute(results);
    205             mResultAdapter.clear();
    206 
    207             if (DEBUG) {
    208                 Log.d(TAG, "searchAndRefresh query=" + mQuery
    209                         + " results=" + ((results == null) ? 0 : results.size()));
    210             }
    211 
    212             if (results == null || results.size() == 0) {
    213                 HeaderItem header =
    214                         new HeaderItem(0, mMainActivity.getString(R.string
    215                                 .search_result_no_result));
    216                 ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
    217                 mResultAdapter.add(new ListRow(header, resultsAdapter));
    218             } else {
    219                 HeaderItem header =
    220                         new HeaderItem(0, mMainActivity.getString(R.string
    221                                 .search_result_title));
    222                 ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
    223                 resultsAdapter.addAll(0, results);
    224                 mResultAdapter.add(new ListRow(header, resultsAdapter));
    225             }
    226             mSearchTask = null;
    227         }
    228     }
    229 }
    230