ProgramGuideSearchFragment.java revision 0645b17e2818b69b996da48fd93731bc8a01f114
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
17package com.android.tv.search;
18
19import android.content.res.Resources;
20import android.graphics.Bitmap;
21import android.graphics.drawable.BitmapDrawable;
22import android.os.AsyncTask;
23import android.os.Bundle;
24import android.support.v17.leanback.app.SearchFragment;
25import android.support.v17.leanback.widget.ArrayObjectAdapter;
26import android.support.v17.leanback.widget.HeaderItem;
27import android.support.v17.leanback.widget.ImageCardView;
28import android.support.v17.leanback.widget.ListRow;
29import android.support.v17.leanback.widget.ListRowPresenter;
30import android.support.v17.leanback.widget.ObjectAdapter;
31import android.support.v17.leanback.widget.OnItemViewClickedListener;
32import android.support.v17.leanback.widget.Presenter;
33import android.support.v17.leanback.widget.Row;
34import android.support.v17.leanback.widget.RowPresenter;
35import android.support.v17.leanback.widget.SearchBar;
36import android.text.TextUtils;
37import android.util.Log;
38import android.view.LayoutInflater;
39import android.view.View;
40import android.view.ViewGroup;
41import com.android.tv.MainActivity;
42import com.android.tv.R;
43import com.android.tv.common.util.PermissionUtils;
44import com.android.tv.util.ImageLoader;
45import java.util.List;
46
47public 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.getChannelDataManager().getChannel(
140                                    result.getChannelId()));
141                }
142            };
143
144    private final ArrayObjectAdapter mResultAdapter =
145            new ArrayObjectAdapter(new ListRowPresenter());
146    private MainActivity mMainActivity;
147    private SearchInterface mSearch;
148    private int mMainCardWidth;
149    private int mMainCardHeight;
150    private SearchTask mSearchTask;
151
152    @Override
153    public void onCreate(Bundle savedInstanceState) {
154        super.onCreate(savedInstanceState);
155
156        mMainActivity = (MainActivity) getActivity();
157        if (PermissionUtils.hasAccessAllEpg(mMainActivity)) {
158            mSearch = new TvProviderSearch(mMainActivity);
159        } else {
160            mSearch = new DataManagerSearch(mMainActivity);
161        }
162        Resources res = getResources();
163        mMainCardWidth = res.getDimensionPixelSize(R.dimen.card_image_layout_width);
164        mMainCardHeight = res.getDimensionPixelSize(R.dimen.card_image_layout_height);
165    }
166
167    @Override
168    public View onCreateView(
169            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
170        View v = super.onCreateView(inflater, container, savedInstanceState);
171        v.setBackgroundResource(R.color.program_guide_scrim);
172
173        setBadgeDrawable(mMainActivity.getDrawable(R.drawable.ic_live_channels_96x96));
174        setSearchResultProvider(mSearchResultProvider);
175        setOnItemViewClickedListener(mItemClickedListener);
176        return v;
177    }
178
179    @Override
180    public void onResume() {
181        super.onResume();
182
183        SearchBar searchBar = (SearchBar) getView().findViewById(R.id.lb_search_bar);
184        searchBar.setSearchQuery("");
185        mResultAdapter.clear();
186    }
187
188    private void searchAndRefresh(String query) {
189        // TODO: Search directly from program data manager for performance.
190        // TODO: Search upcoming programs.
191        if (mSearchTask != null) {
192            mSearchTask.cancel(true);
193        }
194        mSearchTask = new SearchTask(query);
195        mSearchTask.execute();
196    }
197
198    private class SearchTask extends AsyncTask<Void, Void, List<LocalSearchProvider.SearchResult>> {
199        private final String mQuery;
200
201        public SearchTask(String query) {
202            mQuery = query;
203        }
204
205        @Override
206        protected List<LocalSearchProvider.SearchResult> doInBackground(Void... params) {
207            return mSearch.search(
208                    mQuery, SEARCH_RESULT_MAX, TvProviderSearch.ACTION_TYPE_AMBIGUOUS);
209        }
210
211        @Override
212        protected void onPostExecute(List<LocalSearchProvider.SearchResult> results) {
213            super.onPostExecute(results);
214            mResultAdapter.clear();
215
216            if (DEBUG) {
217                Log.d(
218                        TAG,
219                        "searchAndRefresh query="
220                                + mQuery
221                                + " results="
222                                + ((results == null) ? 0 : results.size()));
223            }
224
225            if (results == null || results.size() == 0) {
226                HeaderItem header =
227                        new HeaderItem(
228                                0, mMainActivity.getString(R.string.search_result_no_result));
229                ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
230                mResultAdapter.add(new ListRow(header, resultsAdapter));
231            } else {
232                HeaderItem header =
233                        new HeaderItem(0, mMainActivity.getString(R.string.search_result_title));
234                ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
235                resultsAdapter.addAll(0, results);
236                mResultAdapter.add(new ListRow(header, resultsAdapter));
237            }
238            mSearchTask = null;
239        }
240    }
241}
242