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 import com.android.tv.MainActivity;
     42 import com.android.tv.R;
     43 import com.android.tv.common.util.PermissionUtils;
     44 import com.android.tv.util.images.ImageLoader;
     45 import java.util.List;
     46 
     47 public class ProgramGuideSearchFragment extends SearchFragment {
     48     private static final String TAG = "ProgramGuideSearch";
     49     private static final boolean DEBUG = false;
     50     private static final int SEARCH_RESULT_MAX = 10;
     51 
     52     private final Presenter mPresenter =
     53             new Presenter() {
     54                 @Override
     55                 public Presenter.ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
     56                     if (DEBUG) Log.d(TAG, "onCreateViewHolder");
     57 
     58                     ImageCardView cardView = new ImageCardView(mMainActivity);
     59                     cardView.setFocusable(true);
     60                     cardView.setFocusableInTouchMode(true);
     61                     cardView.setMainImageAdjustViewBounds(false);
     62 
     63                     Resources res = mMainActivity.getResources();
     64                     cardView.setMainImageDimensions(
     65                             res.getDimensionPixelSize(R.dimen.card_image_layout_width),
     66                             res.getDimensionPixelSize(R.dimen.card_image_layout_height));
     67 
     68                     return new Presenter.ViewHolder(cardView);
     69                 }
     70 
     71                 @Override
     72                 public void onBindViewHolder(ViewHolder viewHolder, Object o) {
     73                     ImageCardView cardView = (ImageCardView) viewHolder.view;
     74                     LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
     75                     if (DEBUG) Log.d(TAG, "onBindViewHolder result:" + result);
     76 
     77                     cardView.setTitleText(result.getTitle());
     78                     if (!TextUtils.isEmpty(result.getImageUri())) {
     79                         ImageLoader.loadBitmap(
     80                                 mMainActivity,
     81                                 result.getImageUri(),
     82                                 mMainCardWidth,
     83                                 mMainCardHeight,
     84                                 createImageLoaderCallback(cardView));
     85                     } else {
     86                         cardView.setMainImage(
     87                                 mMainActivity.getDrawable(R.drawable.ic_live_channels_96x96));
     88                     }
     89                 }
     90 
     91                 @Override
     92                 public void onUnbindViewHolder(ViewHolder viewHolder) {
     93                     // Do nothing here.
     94                 }
     95             };
     96 
     97     private static ImageLoader.ImageLoaderCallback<ImageCardView> createImageLoaderCallback(
     98             ImageCardView cardView) {
     99         return new ImageLoader.ImageLoaderCallback<ImageCardView>(cardView) {
    100             @Override
    101             public void onBitmapLoaded(ImageCardView cardView, Bitmap bitmap) {
    102                 cardView.setMainImage(
    103                         new BitmapDrawable(cardView.getContext().getResources(), bitmap));
    104             }
    105         };
    106     }
    107 
    108     private final SearchResultProvider mSearchResultProvider =
    109             new SearchResultProvider() {
    110                 @Override
    111                 public ObjectAdapter getResultsAdapter() {
    112                     return mResultAdapter;
    113                 }
    114 
    115                 @Override
    116                 public boolean onQueryTextChange(String query) {
    117                     searchAndRefresh(query);
    118                     return true;
    119                 }
    120 
    121                 @Override
    122                 public boolean onQueryTextSubmit(String query) {
    123                     searchAndRefresh(query);
    124                     return true;
    125                 }
    126             };
    127 
    128     private final OnItemViewClickedListener mItemClickedListener =
    129             new OnItemViewClickedListener() {
    130                 @Override
    131                 public void onItemClicked(
    132                         Presenter.ViewHolder viewHolder,
    133                         Object o,
    134                         RowPresenter.ViewHolder viewHolder1,
    135                         Row row) {
    136                     LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
    137                     mMainActivity.getFragmentManager().popBackStack();
    138                     mMainActivity.tuneToChannel(
    139                             mMainActivity
    140                                     .getChannelDataManager()
    141                                     .getChannel(result.getChannelId()));
    142                 }
    143             };
    144 
    145     private final ArrayObjectAdapter mResultAdapter =
    146             new ArrayObjectAdapter(new ListRowPresenter());
    147     private MainActivity mMainActivity;
    148     private SearchInterface mSearch;
    149     private int mMainCardWidth;
    150     private int mMainCardHeight;
    151     private SearchTask mSearchTask;
    152 
    153     @Override
    154     public void onCreate(Bundle savedInstanceState) {
    155         super.onCreate(savedInstanceState);
    156 
    157         mMainActivity = (MainActivity) getActivity();
    158         if (PermissionUtils.hasAccessAllEpg(mMainActivity)) {
    159             mSearch = new TvProviderSearch(mMainActivity);
    160         } else {
    161             mSearch = new DataManagerSearch(mMainActivity);
    162         }
    163         Resources res = getResources();
    164         mMainCardWidth = res.getDimensionPixelSize(R.dimen.card_image_layout_width);
    165         mMainCardHeight = res.getDimensionPixelSize(R.dimen.card_image_layout_height);
    166     }
    167 
    168     @Override
    169     public View onCreateView(
    170             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    171         View v = super.onCreateView(inflater, container, savedInstanceState);
    172         v.setBackgroundResource(R.color.program_guide_scrim);
    173 
    174         setBadgeDrawable(mMainActivity.getDrawable(R.drawable.ic_live_channels_96x96));
    175         setSearchResultProvider(mSearchResultProvider);
    176         setOnItemViewClickedListener(mItemClickedListener);
    177         return v;
    178     }
    179 
    180     @Override
    181     public void onResume() {
    182         super.onResume();
    183 
    184         SearchBar searchBar = (SearchBar) getView().findViewById(R.id.lb_search_bar);
    185         searchBar.setSearchQuery("");
    186         mResultAdapter.clear();
    187     }
    188 
    189     private void searchAndRefresh(String query) {
    190         // TODO: Search directly from program data manager for performance.
    191         // TODO: Search upcoming programs.
    192         if (mSearchTask != null) {
    193             mSearchTask.cancel(true);
    194         }
    195         mSearchTask = new SearchTask(query);
    196         mSearchTask.execute();
    197     }
    198 
    199     private class SearchTask extends AsyncTask<Void, Void, List<LocalSearchProvider.SearchResult>> {
    200         private final String mQuery;
    201 
    202         public SearchTask(String query) {
    203             mQuery = query;
    204         }
    205 
    206         @Override
    207         protected List<LocalSearchProvider.SearchResult> doInBackground(Void... params) {
    208             return mSearch.search(
    209                     mQuery, SEARCH_RESULT_MAX, TvProviderSearch.ACTION_TYPE_AMBIGUOUS);
    210         }
    211 
    212         @Override
    213         protected void onPostExecute(List<LocalSearchProvider.SearchResult> results) {
    214             super.onPostExecute(results);
    215             mResultAdapter.clear();
    216 
    217             if (DEBUG) {
    218                 Log.d(
    219                         TAG,
    220                         "searchAndRefresh query="
    221                                 + mQuery
    222                                 + " results="
    223                                 + ((results == null) ? 0 : results.size()));
    224             }
    225 
    226             if (results == null || results.size() == 0) {
    227                 HeaderItem header =
    228                         new HeaderItem(
    229                                 0, mMainActivity.getString(R.string.search_result_no_result));
    230                 ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
    231                 mResultAdapter.add(new ListRow(header, resultsAdapter));
    232             } else {
    233                 HeaderItem header =
    234                         new HeaderItem(0, mMainActivity.getString(R.string.search_result_title));
    235                 ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
    236                 resultsAdapter.addAll(0, results);
    237                 mResultAdapter.add(new ListRow(header, resultsAdapter));
    238             }
    239             mSearchTask = null;
    240         }
    241     }
    242 }
    243