Java tutorial
/* * Copyright (c) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.kraenksoft.c3tv.ui; import android.Manifest; import android.app.Activity; import android.app.LoaderManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.CursorLoader; import android.content.Intent; import android.content.Loader; import android.content.pm.PackageManager; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.support.v17.leanback.widget.ArrayObjectAdapter; import android.support.v17.leanback.widget.CursorObjectAdapter; import android.support.v17.leanback.widget.HeaderItem; import android.support.v17.leanback.widget.ImageCardView; import android.support.v17.leanback.widget.ListRow; import android.support.v17.leanback.widget.ListRowPresenter; import android.support.v17.leanback.widget.ObjectAdapter; import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; import android.support.v17.leanback.widget.SpeechRecognitionCallback; import android.support.v4.app.ActivityOptionsCompat; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import de.kraenksoft.c3tv.BuildConfig; import de.kraenksoft.c3tv.R; import de.kraenksoft.c3tv.data.VideoContract; import de.kraenksoft.c3tv.model.Video; import de.kraenksoft.c3tv.model.VideoCursorMapper; import de.kraenksoft.c3tv.presenter.CardPresenter; /* * This class demonstrates how to do in-app search */ public class SearchFragment extends android.support.v17.leanback.app.SearchFragment implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider, LoaderManager.LoaderCallbacks<Cursor> { private static final String TAG = "SearchFragment"; private static final boolean DEBUG = BuildConfig.DEBUG; private static final boolean FINISH_ON_RECOGNIZER_CANCELED = true; private static final int REQUEST_SPEECH = 0x00000010; private final Handler mHandler = new Handler(); private ArrayObjectAdapter mRowsAdapter; private String mQuery; private final CursorObjectAdapter mVideoCursorAdapter = new CursorObjectAdapter(new CardPresenter()); private int mSearchLoaderId = 1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); mVideoCursorAdapter.setMapper(new VideoCursorMapper()); setSearchResultProvider(this); setOnItemViewClickedListener(new ItemViewClickedListener()); if (!hasPermission(Manifest.permission.RECORD_AUDIO)) { // SpeechRecognitionCallback is not required and if not provided recognition will be // handled using internal speech recognizer, in which case you must have RECORD_AUDIO // permission setSpeechRecognitionCallback(new SpeechRecognitionCallback() { @Override public void recognizeSpeech() { try { startActivityForResult(getRecognizerIntent(), REQUEST_SPEECH); } catch (ActivityNotFoundException e) { Log.e(TAG, "Cannot find activity for speech recognizer", e); } } }); } } @Override public void onPause() { mHandler.removeCallbacksAndMessages(null); super.onPause(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_SPEECH: switch (resultCode) { case Activity.RESULT_OK: setSearchQuery(data, true); break; case Activity.RESULT_CANCELED: // Once recognizer canceled, user expects the current activity to process // the same BACK press as user doesn't know about overlay activity. // However, you may not want this behaviour as it makes harder to // fall back to keyboard input. if (FINISH_ON_RECOGNIZER_CANCELED) { if (!hasResults()) { if (DEBUG) Log.v(TAG, "Delegating BACK press from recognizer"); getActivity().onBackPressed(); } } break; // the rest includes various recognizer errors, see {@link RecognizerIntent} } break; } } @Override public ObjectAdapter getResultsAdapter() { return mRowsAdapter; } @Override public boolean onQueryTextChange(String newQuery) { if (DEBUG) Log.i(TAG, String.format("Search text changed: %s", newQuery)); loadQuery(newQuery); return true; } @Override public boolean onQueryTextSubmit(String query) { if (DEBUG) Log.i(TAG, String.format("Search text submitted: %s", query)); loadQuery(query); return true; } public boolean hasResults() { return mRowsAdapter.size() > 0; } private boolean hasPermission(final String permission) { final Context context = getActivity(); return PackageManager.PERMISSION_GRANTED == context.getPackageManager().checkPermission(permission, context.getPackageName()); } private void loadQuery(String query) { if (!TextUtils.isEmpty(query) && !query.equals("nil")) { mQuery = query; getLoaderManager().initLoader(mSearchLoaderId++, null, this); } } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { String query = mQuery; return new CursorLoader(getActivity(), VideoContract.VideoEntry.CONTENT_URI, null, // Return all fields. VideoContract.VideoEntry.COLUMN_NAME + " LIKE ? OR " + VideoContract.VideoEntry.COLUMN_DESC + " LIKE ?", new String[] { "%" + query + "%", "%" + query + "%" }, null // Default sort order ); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { if (cursor != null && cursor.moveToFirst()) { mVideoCursorAdapter.changeCursor(cursor); mRowsAdapter.clear(); HeaderItem header = new HeaderItem(getString(R.string.search_results, mQuery)); ListRow row = new ListRow(header, mVideoCursorAdapter); mRowsAdapter.add(row); } else { // No results were found. mRowsAdapter.clear(); HeaderItem header = new HeaderItem(getString(R.string.no_search_results, mQuery)); ListRow row = new ListRow(header, new ArrayObjectAdapter()); mRowsAdapter.add(row); } } @Override public void onLoaderReset(Loader<Cursor> loader) { mVideoCursorAdapter.changeCursor(null); } private final class ItemViewClickedListener implements OnItemViewClickedListener { @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { if (item instanceof Video) { Video video = (Video) item; Intent intent = new Intent(getActivity(), VideoDetailsActivity.class); intent.putExtra(VideoDetailsActivity.VIDEO, video); Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), ((ImageCardView) itemViewHolder.view).getMainImageView(), VideoDetailsActivity.SHARED_ELEMENT_NAME).toBundle(); getActivity().startActivity(intent, bundle); } else { Toast.makeText(getActivity(), ((String) item), Toast.LENGTH_SHORT).show(); } } } }