• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.settings.widget;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.res.TypedArray;
22 import android.graphics.SurfaceTexture;
23 import android.media.MediaPlayer;
24 import android.net.Uri;
25 import android.support.annotation.VisibleForTesting;
26 import android.support.v7.preference.Preference;
27 import android.support.v7.preference.PreferenceViewHolder;
28 import android.util.AttributeSet;
29 import android.util.Log;
30 import android.view.Surface;
31 import android.view.TextureView;
32 import android.view.View;
33 import android.widget.ImageView;
34 
35 import com.android.settings.R;
36 
37 /**
38  * A full width preference that hosts a MP4 video.
39  */
40 public class VideoPreference extends Preference {
41 
42     private static final String TAG = "VideoPreference";
43     private final Context mContext;
44 
45     private Uri mVideoPath;
46     @VisibleForTesting
47     MediaPlayer mMediaPlayer;
48     @VisibleForTesting
49     boolean mAnimationAvailable;
50     private boolean mVideoReady;
51     private boolean mVideoPaused;
52     private float mAspectRadio = 1.0f;
53     private int mPreviewResource;
54 
VideoPreference(Context context, AttributeSet attrs)55     public VideoPreference(Context context, AttributeSet attrs) {
56         super(context, attrs);
57         mContext = context;
58         TypedArray attributes = context.getTheme().obtainStyledAttributes(
59                 attrs,
60                 com.android.settings.R.styleable.VideoPreference,
61                 0, 0);
62         try {
63             int animation = attributes.getResourceId(R.styleable.VideoPreference_animation, 0);
64             mVideoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
65                     .authority(context.getPackageName())
66                     .appendPath(String.valueOf(animation))
67                     .build();
68             mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
69             if (mMediaPlayer != null && mMediaPlayer.getDuration() > 0) {
70                 setVisible(true);
71                 setLayoutResource(R.layout.video_preference);
72 
73                 mPreviewResource = attributes.getResourceId(
74                         R.styleable.VideoPreference_preview, 0);
75 
76                 mMediaPlayer.setOnSeekCompleteListener(mp -> mVideoReady = true);
77 
78                 mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true));
79                 mAnimationAvailable = true;
80                 updateAspectRatio();
81             } else {
82                 setVisible(false);
83             }
84         } catch (Exception e) {
85             Log.w(TAG, "Animation resource not found. Will not show animation.");
86         } finally {
87             attributes.recycle();
88         }
89     }
90 
91     @Override
onBindViewHolder(PreferenceViewHolder holder)92     public void onBindViewHolder(PreferenceViewHolder holder) {
93         super.onBindViewHolder(holder);
94 
95         if (!mAnimationAvailable) {
96             return;
97         }
98 
99         final TextureView video = (TextureView) holder.findViewById(R.id.video_texture_view);
100         final ImageView imageView = (ImageView) holder.findViewById(R.id.video_preview_image);
101         final ImageView playButton = (ImageView) holder.findViewById(R.id.video_play_button);
102         final AspectRatioFrameLayout layout = (AspectRatioFrameLayout) holder.findViewById(
103                 R.id.video_container);
104 
105         imageView.setImageResource(mPreviewResource);
106         layout.setAspectRatio(mAspectRadio);
107 
108         video.setOnClickListener(v -> {
109             if (mMediaPlayer != null) {
110                 if (mMediaPlayer.isPlaying()) {
111                     mMediaPlayer.pause();
112                     playButton.setVisibility(View.VISIBLE);
113                     mVideoPaused = true;
114                 } else {
115                     mMediaPlayer.start();
116                     playButton.setVisibility(View.GONE);
117                     mVideoPaused = false;
118                 }
119             }
120         });
121 
122         video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
123             @Override
124             public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
125                     int height) {
126                 if (mMediaPlayer != null) {
127                     mMediaPlayer.setSurface(new Surface(surfaceTexture));
128                     mVideoReady = false;
129                     mMediaPlayer.seekTo(0);
130                 }
131             }
132 
133             @Override
134             public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
135                     int height) {
136             }
137 
138             @Override
139             public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
140                 imageView.setVisibility(View.VISIBLE);
141                 return false;
142             }
143 
144             @Override
145             public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
146                 if (mVideoReady) {
147                     if (imageView.getVisibility() == View.VISIBLE) {
148                         imageView.setVisibility(View.GONE);
149                     }
150                     if (!mVideoPaused && mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
151                         mMediaPlayer.start();
152                         playButton.setVisibility(View.GONE);
153                     }
154                 }
155                 if (mMediaPlayer != null && !mMediaPlayer.isPlaying() &&
156                         playButton.getVisibility() != View.VISIBLE) {
157                     playButton.setVisibility(View.VISIBLE);
158                 }
159             }
160         });
161     }
162 
163     @Override
onDetached()164     public void onDetached() {
165         if (mMediaPlayer != null) {
166             mMediaPlayer.stop();
167             mMediaPlayer.reset();
168             mMediaPlayer.release();
169         }
170         super.onDetached();
171     }
172 
onViewVisible(boolean videoPaused)173     public void onViewVisible(boolean videoPaused) {
174         mVideoPaused = videoPaused;
175         if (mVideoReady && mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
176             mMediaPlayer.seekTo(0);
177         }
178     }
179 
onViewInvisible()180     public void onViewInvisible() {
181         if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
182             mMediaPlayer.pause();
183         }
184     }
185 
isVideoPaused()186     public boolean isVideoPaused() {
187         return mVideoPaused;
188     }
189 
190     @VisibleForTesting
updateAspectRatio()191     void updateAspectRatio() {
192         mAspectRadio = mMediaPlayer.getVideoWidth() / (float)mMediaPlayer.getVideoHeight();
193     }
194 
195 }
196