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