• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package com.example.android.leanback;
15 
16 import android.content.Context;
17 import android.content.Intent;
18 import android.graphics.Bitmap;
19 import android.net.Uri;
20 import android.os.Bundle;
21 import android.os.Handler;
22 import android.support.v17.leanback.app.DetailsFragmentBackgroundController;
23 import android.support.v17.leanback.media.MediaPlayerAdapter;
24 import android.support.v17.leanback.media.MediaPlayerGlue;
25 import android.support.v17.leanback.media.PlaybackGlue;
26 import android.support.v17.leanback.media.PlaybackTransportControlGlue;
27 import android.support.v17.leanback.widget.Action;
28 import android.support.v17.leanback.widget.ArrayObjectAdapter;
29 import android.support.v17.leanback.widget.ClassPresenterSelector;
30 import android.support.v17.leanback.widget.DetailsOverviewRow;
31 import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
32 import android.support.v17.leanback.widget.FullWidthDetailsOverviewSharedElementHelper;
33 import android.support.v17.leanback.widget.HeaderItem;
34 import android.support.v17.leanback.widget.ImageCardView;
35 import android.support.v17.leanback.widget.ListRow;
36 import android.support.v17.leanback.widget.ListRowPresenter;
37 import android.support.v17.leanback.widget.OnActionClickedListener;
38 import android.support.v17.leanback.widget.OnItemViewClickedListener;
39 import android.support.v17.leanback.widget.OnItemViewSelectedListener;
40 import android.support.v17.leanback.widget.Presenter;
41 import android.support.v17.leanback.widget.Row;
42 import android.support.v17.leanback.widget.RowPresenter;
43 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
44 import android.support.v4.app.ActivityOptionsCompat;
45 import android.support.v4.content.res.ResourcesCompat;
46 import android.util.Log;
47 import android.view.LayoutInflater;
48 import android.view.View;
49 import android.view.ViewGroup;
50 
51 public class NewDetailsFragment extends android.support.v17.leanback.app.DetailsFragment {
52 
53     private static final String TAG = "leanback.DetailsFragment";
54     private static final String ITEM = "item";
55 
56     private static final int NUM_ROWS = 3;
57     private ArrayObjectAdapter mRowsAdapter;
58     private PhotoItem mPhotoItem;
59     final CardPresenter cardPresenter = new CardPresenter();
60 
61     private static final int ACTION_PLAY = 1;
62     private static final int ACTION_RENT = 2;
63     private static final int ACTION_BUY = 3;
64 
65     private boolean TEST_SHARED_ELEMENT_TRANSITION = true;
66     private boolean TEST_BACKGROUND_PLAYER;
67 
68     private static final long TIME_TO_LOAD_OVERVIEW_ROW_MS = 1000;
69     private static final long TIME_TO_LOAD_RELATED_ROWS_MS = 2000;
70 
71     private Action mActionPlay;
72     private Action mActionRent;
73     private Action mActionBuy;
74 
75     private FullWidthDetailsOverviewSharedElementHelper mHelper;
76     private BackgroundHelper mBackgroundHelper; // used to download bitmap async.
77     private final DetailsFragmentBackgroundController mDetailsBackground =
78             new DetailsFragmentBackgroundController(this);
79 
setupTrailerVideo()80     void setupTrailerVideo() {
81         MediaPlayerGlue mediaPlayerGlue = new MediaPlayerGlue(getActivity());
82         mDetailsBackground.setupVideoPlayback(mediaPlayerGlue);
83         mediaPlayerGlue.setMode(MediaPlayerGlue.REPEAT_ONE);
84         mediaPlayerGlue.setArtist("A Googler");
85         mediaPlayerGlue.setTitle("Diving with Sharks Trailer");
86         mediaPlayerGlue.setMediaSource(Uri.parse("android.resource://com.example.android.leanback/"
87                 + "raw/browse"));
88     }
89 
setupMainVideo()90     void setupMainVideo() {
91         Context context = getActivity();
92         MediaPlayerAdapter adapter = new MediaPlayerAdapter(context);
93         PlaybackTransportControlGlue<MediaPlayerAdapter> mediaPlayerGlue =
94                 new PlaybackTransportControlGlue(context, adapter);
95         mDetailsBackground.setupVideoPlayback(mediaPlayerGlue);
96         mediaPlayerGlue.setSubtitle("A Googler");
97         mediaPlayerGlue.setTitle("Diving with Sharks");
98         mediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(
99                 "https://storage.googleapis.com/android-tv/Sample videos/April Fool's "
100                         + "2013/Explore Treasure Mode with Google Maps.mp4"));
101         mediaPlayerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
102             @Override
103             public void onPreparedStateChanged(PlaybackGlue glue) {
104                 super.onPreparedStateChanged(glue);
105                 PlaybackTransportControlGlue controlGlue = (PlaybackTransportControlGlue) glue;
106                 controlGlue.setSeekProvider(new PlaybackSeekDiskDataProvider(
107                         controlGlue.getDuration(), 1000,
108                         "/sdcard/seek/frame_%04d.jpg"));
109             }
110         });
111     }
112 
113     @Override
onCreate(Bundle savedInstanceState)114     public void onCreate(Bundle savedInstanceState) {
115         Log.i(TAG, "onCreate");
116         super.onCreate(savedInstanceState);
117 
118         mBackgroundHelper = new BackgroundHelper(getActivity());
119         mDetailsBackground.enableParallax();
120         if (TEST_BACKGROUND_PLAYER) {
121             if (MovieData.sStatus == MovieData.STATUS_INIT) {
122                 // not own/rented, play trailer
123                 setupTrailerVideo();
124             } else {
125                 // bought or rented, play the main content
126                 setupMainVideo();
127                 // hide details main ui
128                 mDetailsBackground.switchToVideo();
129             }
130         }
131 
132         final Context context = getActivity();
133         setBadgeDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_title,
134                 context.getTheme()));
135         setTitle("Leanback Sample App");
136         if (!TEST_BACKGROUND_PLAYER) {
137             setOnSearchClickedListener(new View.OnClickListener() {
138                 @Override
139                 public void onClick(View view) {
140                     Intent intent = new Intent(getActivity(), SearchActivity.class);
141                     startActivity(intent);
142                 }
143             });
144         }
145 
146         mActionPlay = new Action(ACTION_PLAY, "Play");
147         mActionRent = new Action(ACTION_RENT, "Rent", "$3.99", ResourcesCompat.getDrawable(
148                 context.getResources(), R.drawable.ic_action_a, context.getTheme()));
149         mActionBuy = new Action(ACTION_BUY, "Buy $9.99");
150 
151         ClassPresenterSelector ps = new ClassPresenterSelector();
152         FullWidthDetailsOverviewRowPresenter dorPresenter =
153                 new FullWidthDetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
154         dorPresenter.setOnActionClickedListener(new OnActionClickedListener() {
155             @Override
156             public void onActionClicked(Action action) {
157                 final Context context = getActivity();
158                 DetailsOverviewRow dor = (DetailsOverviewRow) mRowsAdapter.get(0);
159                 if (action.getId() == ACTION_BUY) {
160                     // on the UI thread, we can modify actions adapter directly
161                     SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter)
162                             dor.getActionsAdapter();
163                     actions.set(ACTION_PLAY, mActionPlay);
164                     actions.clear(ACTION_RENT);
165                     actions.clear(ACTION_BUY);
166                     boolean previousRented = MovieData.sStatus == MovieData.STATUS_RENTED;
167                     MovieData.sStatus = MovieData.STATUS_OWN;
168                     dor.setItem(getDisplayTitle(mPhotoItem.getTitle()));
169                     dor.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(),
170                             R.drawable.details_img_16x9, context.getTheme()));
171                     if (TEST_BACKGROUND_PLAYER) {
172                         if (!previousRented) {
173                             setupMainVideo();
174                             mDetailsBackground.switchToVideo();
175                         }
176                     } else {
177                         Intent intent = new Intent(context, PlaybackOverlayActivity.class);
178                         getActivity().startActivity(intent);
179                     }
180                 } else if (action.getId() == ACTION_RENT) {
181                     // on the UI thread, we can modify actions adapter directly
182                     SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter)
183                             dor.getActionsAdapter();
184                     actions.set(ACTION_PLAY, mActionPlay);
185                     actions.clear(ACTION_RENT);
186                     MovieData.sStatus = MovieData.STATUS_RENTED;
187                     dor.setItem(getDisplayTitle(mPhotoItem.getTitle()));
188                     if (TEST_BACKGROUND_PLAYER) {
189                         setupMainVideo();
190                         mDetailsBackground.switchToVideo();
191                     } else {
192                         Intent intent = new Intent(context, PlaybackOverlayActivity.class);
193                         getActivity().startActivity(intent);
194                     }
195                 } else if (action.getId() == ACTION_PLAY) {
196                     if (TEST_BACKGROUND_PLAYER) {
197                         mDetailsBackground.switchToVideo();
198                     } else {
199                         Intent intent = new Intent(context, PlaybackOverlayActivity.class);
200                         getActivity().startActivity(intent);
201                     }
202                 }
203             }
204         });
205 
206         ps.addClassPresenter(DetailsOverviewRow.class, dorPresenter);
207         ps.addClassPresenter(ListRow.class, new ListRowPresenter());
208 
209         mRowsAdapter = new ArrayObjectAdapter(ps);
210         updateAdapter();
211 
212         setOnItemViewClickedListener(new OnItemViewClickedListener() {
213             @Override
214             public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
215                     RowPresenter.ViewHolder rowViewHolder, Row row) {
216                 Log.i(TAG, "onItemClicked: " + item + " row " + row);
217                 if (item instanceof PhotoItem) {
218                     Intent intent = new Intent(getActivity(), DetailsActivity.class);
219                     intent.putExtra(DetailsActivity.EXTRA_ITEM, (PhotoItem) item);
220 
221                     Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
222                             getActivity(),
223                             ((ImageCardView) itemViewHolder.view).getMainImageView(),
224                             DetailsActivity.SHARED_ELEMENT_NAME).toBundle();
225                     getActivity().startActivity(intent, bundle);
226                 }
227             }
228         });
229         setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
230             @Override
231             public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
232                     RowPresenter.ViewHolder rowViewHolder, Row row) {
233                 Log.i(TAG, "onItemSelected: " + item + " row " + row);
234             }
235         });
236 
237         if (TEST_SHARED_ELEMENT_TRANSITION) {
238             mHelper = new FullWidthDetailsOverviewSharedElementHelper();
239             mHelper.setSharedElementEnterTransition(getActivity(),
240                     DetailsActivity.SHARED_ELEMENT_NAME);
241             dorPresenter.setListener(mHelper);
242             dorPresenter.setParticipatingEntranceTransition(false);
243         } else {
244             dorPresenter.setParticipatingEntranceTransition(true);
245         }
246     }
247 
248     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)249     public View onCreateView(LayoutInflater inflater, ViewGroup container,
250             Bundle savedInstanceState) {
251         View view = super.onCreateView(inflater, container, savedInstanceState);
252         return view;
253     }
254 
setBackgroundVideo(boolean backgroundVideo)255     public void setBackgroundVideo(boolean backgroundVideo) {
256         TEST_BACKGROUND_PLAYER = backgroundVideo;
257     }
258 
setItem(PhotoItem photoItem)259     public void setItem(PhotoItem photoItem) {
260         mPhotoItem = photoItem;
261         updateAdapter();
262     }
263 
getDisplayTitle(String title)264     static String getDisplayTitle(String title) {
265         switch (MovieData.sStatus) {
266             case MovieData.STATUS_OWN:
267                 title = title + "(Owned)";
268                 break;
269             case MovieData.STATUS_RENTED:
270                 title = title + "(Rented)";
271                 break;
272             case MovieData.STATUS_INIT:
273             default:
274         }
275         return title;
276     }
277 
updateAdapter()278     void updateAdapter() {
279         if (mRowsAdapter == null) {
280             return;
281         }
282         mRowsAdapter.clear();
283         new Handler().postDelayed(new Runnable() {
284             @Override
285             public void run() {
286                 final Context context = getActivity();
287                 if (context == null) {
288                     return;
289                 }
290 
291                 DetailsOverviewRow dor = new DetailsOverviewRow(
292                         getDisplayTitle(mPhotoItem.getTitle()));
293                 dor.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(),
294                         mPhotoItem.getImageResourceId(), context.getTheme()));
295                 SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter();
296                 switch (MovieData.sStatus) {
297                     case MovieData.STATUS_INIT:
298                         adapter.set(ACTION_RENT, mActionRent);
299                         adapter.set(ACTION_BUY, mActionBuy);
300                         break;
301                     case MovieData.STATUS_OWN:
302                         adapter.set(ACTION_PLAY, mActionPlay);
303                         break;
304                     case MovieData.STATUS_RENTED:
305                         adapter.set(ACTION_PLAY, mActionPlay);
306                         adapter.set(ACTION_BUY, mActionBuy);
307                         break;
308                 }
309                 dor.setActionsAdapter(adapter);
310                 mRowsAdapter.add(0, dor);
311                 setSelectedPosition(0, true);
312                 if (TEST_SHARED_ELEMENT_TRANSITION) {
313                     if (mHelper != null && !mHelper.getAutoStartSharedElementTransition()) {
314                         mHelper.startPostponedEnterTransition();
315                     }
316                 }
317             }
318         }, TIME_TO_LOAD_OVERVIEW_ROW_MS);
319 
320         new Handler().postDelayed(new Runnable() {
321             @Override
322             public void run() {
323                 if (getActivity() == null) {
324                     return;
325                 }
326                 for (int i = 0; i < NUM_ROWS; ++i) {
327                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
328                     listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1));
329                     listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2));
330                     listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_3));
331                     listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4));
332                     HeaderItem header = new HeaderItem(i, "Row " + i);
333                     mRowsAdapter.add(new ListRow(header, listRowAdapter));
334                 }
335             }
336         }, TIME_TO_LOAD_RELATED_ROWS_MS);
337         setAdapter(mRowsAdapter);
338     }
339 
340     @Override
onStart()341     public void onStart() {
342         super.onStart();
343 
344         // Restore background drawable in onStart():
345         mBackgroundHelper.loadBitmap(R.drawable.spiderman,
346                 new BackgroundHelper.BitmapLoadCallback() {
347                     @Override
348                     public void onBitmapLoaded(Bitmap bitmap) {
349                         mDetailsBackground.setCoverBitmap(bitmap);
350                     }
351                 });
352     }
353 
354     @Override
onStop()355     public void onStop() {
356         mDetailsBackground.setCoverBitmap(null);
357         super.onStop();
358     }
359 }
360