88import android .media .AudioManager ;
99import android .media .MediaMetadataRetriever ;
1010import android .media .MediaPlayer ;
11+ import android .os .Build ;
1112import android .support .annotation .Nullable ;
1213import android .util .AttributeSet ;
1314import android .util .Log ;
15+ import android .view .MotionEvent ;
1416import android .view .Surface ;
1517import android .view .TextureView ;
1618
@@ -38,6 +40,9 @@ public class VideoView extends TextureView implements TextureView.SurfaceTexture
3840 // An optional listener for when videos have reached the end
3941 @ Nullable private MediaPlayer .OnCompletionListener mOnCompletionListener ;
4042
43+ // An optional listener for when videos are paused/played
44+ @ Nullable private EventListener mEventListener ;
45+
4146 // If true, the video should be mirrored
4247 private boolean mIsMirrored = false ;
4348
@@ -108,7 +113,7 @@ public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int h
108113 public boolean onSurfaceTextureDestroyed (SurfaceTexture texture ) {
109114 if (DEBUG ) Log .d (TAG , "Texture destroyed" );
110115 mIsAvailable = false ;
111- mIsPlaying = false ;
116+ setPlayingState ( false ) ;
112117
113118 ensureMediaPlayer ();
114119 mMediaPlayer .release ();
@@ -132,7 +137,7 @@ private void ensureMediaPlayer() {
132137 mMediaPlayer .setOnCompletionListener (new MediaPlayer .OnCompletionListener () {
133138 @ Override
134139 public void onCompletion (MediaPlayer mediaPlayer ) {
135- mIsPlaying = false ;
140+ setPlayingState ( false ) ;
136141 if (mOnCompletionListener != null ) {
137142 mOnCompletionListener .onCompletion (mediaPlayer );
138143 }
@@ -144,6 +149,10 @@ public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
144149 mOnCompletionListener = listener ;
145150 }
146151
152+ public void setEventListener (EventListener listener ) {
153+ mEventListener = listener ;
154+ }
155+
147156 protected void prepare () {
148157 if (DEBUG ) Log .d (TAG , "Preparing video" );
149158 ensureMediaPlayer ();
@@ -155,9 +164,15 @@ protected void prepare() {
155164 retriever .setDataSource (fileDescriptor );
156165 int width = extractAsInt (retriever , MediaMetadataRetriever .METADATA_KEY_VIDEO_WIDTH );
157166 int height = extractAsInt (retriever , MediaMetadataRetriever .METADATA_KEY_VIDEO_HEIGHT );
167+ int rotation = Build .VERSION .SDK_INT < 17 ? 0 : extractAsInt (retriever , MediaMetadataRetriever .METADATA_KEY_VIDEO_ROTATION );
158168 retriever .release ();
159- if (DEBUG ) Log .d (TAG , String .format ("Video metadata: width=%d, height=%d" , width , height ));
169+ if (DEBUG ) Log .d (TAG , String .format ("Video metadata: width=%d, height=%d, rotation=%d " , width , height , rotation ));
160170
171+ if (rotation == 90 || rotation == 270 ) {
172+ int temp = width ;
173+ width = height ;
174+ height = temp ;
175+ }
161176 transformPreview (width , height );
162177
163178 Surface surface = new Surface (getSurfaceTexture ());
@@ -223,7 +238,7 @@ public boolean play() {
223238
224239 try {
225240 mMediaPlayer .start ();
226- mIsPlaying = true ;
241+ setPlayingState ( true ) ;
227242 return true ;
228243 } catch (IllegalStateException e ) {
229244 if (DEBUG ) e .printStackTrace ();
@@ -234,14 +249,15 @@ public boolean play() {
234249 public boolean pause () {
235250 if (DEBUG ) Log .d (TAG , "pause()" );
236251 ensureMediaPlayer ();
237- mIsPlaying = false ;
238252
239253 try {
240254 mMediaPlayer .pause ();
255+ setPlayingState (false );
241256 return true ;
242257 } catch (IllegalStateException e ) {
243258 if (DEBUG ) e .printStackTrace ();
244259 }
260+
245261 return false ;
246262 }
247263
@@ -255,6 +271,19 @@ public boolean isPlaying() {
255271 return false ;
256272 }
257273
274+ private void setPlayingState (boolean state ) {
275+ if (mIsPlaying != state ) {
276+ mIsPlaying = state ;
277+ if (mEventListener != null ) {
278+ if (mIsPlaying ) {
279+ mEventListener .onPlay ();
280+ } else {
281+ mEventListener .onPause ();
282+ }
283+ }
284+ }
285+ }
286+
258287 public void setShouldMirror (boolean mirror ) {
259288 mIsMirrored = mirror ;
260289 }
@@ -274,14 +303,6 @@ void transformPreview(int videoWidth, int videoHeight) {
274303
275304 Matrix matrix = new Matrix ();
276305
277- // Usually, we'd check device orientation. However, on the Pixel C, the orientation is
278- // reversed from what you'd expect. What we really care about is width/height ratio.
279- if (viewWidth < viewHeight ) {
280- int temp = videoWidth ;
281- videoWidth = videoHeight ;
282- videoHeight = temp ;
283- }
284-
285306 float aspectRatio = (float ) videoHeight / (float ) videoWidth ;
286307 int newWidth , newHeight ;
287308 if (viewHeight > viewWidth * aspectRatio ) {
@@ -336,4 +357,36 @@ private void showSurface() {
336357 mOriginalMatrix = null ;
337358 }
338359 }
360+
361+ private void onTap () {
362+ if (isPlaying ()) {
363+ pause ();
364+ } else {
365+ play ();
366+ }
367+ }
368+
369+ @ Override
370+ public boolean onTouchEvent (MotionEvent event ) {
371+ if (!super .onTouchEvent (event )) {
372+ switch (event .getAction ()) {
373+ case MotionEvent .ACTION_DOWN :
374+ setPressed (true );
375+ break ;
376+ case MotionEvent .ACTION_CANCEL :
377+ setPressed (false );
378+ break ;
379+ case MotionEvent .ACTION_UP :
380+ onTap ();
381+ setPressed (false );
382+ break ;
383+ }
384+ }
385+ return true ;
386+ }
387+
388+ public interface EventListener {
389+ void onPlay ();
390+ void onPause ();
391+ }
339392}
0 commit comments