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