0

I am a new developer working on Samsung Galaxy tab (model SM-T210R, Android version 4.4.2.

I'd like to develop an app with two media players alternatively playing but only one shown on the screen.

Currently, I am able to alternatively play two video files (one pause and the other play and then switch) by mainly following the good example from user MH (thanks) in How to play multiple video files simultaneously in one layout side by side in different view in Android. I am using a linear layout.

However, two surfaceviews are being shown on the screen all the time, including the one from the media player being paused.

Could anyone instruct how to show on the screen only the one from the active media player? Thanks a lot.

I have tried the following but they did not work (maybe I missed something?): (a) Overlap one surface view on the top of the other and set the top one transparent - However, once the media player associated with the top surface view is being played, the top surface view is not transparent anymore. Is there a way to set it to transparent in that scenario? Also, can I dynamically turn on and off the transparency setting?

(b) Use ViewSwitch class - Unfortunately, I cannot change from one surface view to another.

(c) I also tried the one in How to display two videos simultaneously with surface view. In this case, I see two video views but I wanted to have one.

(d) I also tried this one android how to resize video width and height in surface view for media player. It cannot solve my two surface view into one display problem.

Thanks

Community
  • 1
  • 1
Shalina Hu
  • 31
  • 1
  • 4
  • You're probably better off using a TextureView. Those can be used for video output, and obey all of the rules that regular Views follow. Each SurfaceView is providing a Surface on a layer independent of the View layer, and it can be difficult to manage them. See Grafika (https://github.com/google/grafika) for examples. – fadden Mar 20 '15 at 15:30
  • Thanks. I tried the TextureView a while back but got errors when I called setSurfaceTextureListener() I got a null pointer exception. I will check this later. – Shalina Hu Mar 21 '15 at 14:04

2 Answers2

0

Create a layout with two FrameLayouts, if the videos are to appear side by side than put them in a linear layout as you have it. If only one or the other are supposed to show, then put them in the same parent FrameLayout

This an example of one or the other:

<FrameLayout>
   <FrameLayout id="video1"/>
   <FrameLayout id="video2"/>
</FrameLayout>

In the java code, add each of the SurfaceViews as a child to the FrameLayout

When video1 is paused, set its visibility to hidden and the other to visible, when that is paused, switch the visibility again.

Update

Use only the FrameLayout in the xml files. Create an instance of a SurfaceView in the Java code and apply LayoutParams if needed, then attach them to the FrameLayouts

FrameLayout l1 = (FrameLayout) findViewById(R.id.video1);
FrameLayout l2 = (FrameLayout) findViewById(R.id.video2);

l2.setVisibility(View.INVISIBLE);  // You can use GONE as well

SurfaceView sv1 = new SurfaceView(...);
SurfaceView sv2 = new SurfaceView(...);

l1.addView(sv1);
l2.addView(sv2);

Now you can alternate between VISIBLE and INVISIBLE based on the play state of the video.

Gary Bak
  • 4,746
  • 4
  • 22
  • 39
  • Gary Bak, thank you very much for your suggestion. However, I still do not know how to do it. Could you post a sample code here? For example, how to add each SurfaceView as a child to the FrameLayout, and how to change its visibility in java code. Also, in activity_main.xml, do I need to define Surfaceview in each of embedded FrameLayout such as: – Shalina Hu Mar 20 '15 at 14:16
  • Okay, Gary. I think I understand what you meant. I tried this. – Shalina Hu Mar 21 '15 at 00:17
  • Basically, I defined SurfaceViews directly in the layout creation xml files. Then, I alternatively set one of frame layout invisible like this, fLayout1 = (FrameLayout)findViewById(R.id.video1); fLayout2 = (FrameLayout)findViewById(R.id.video2); ...alternating the following, fLayout1.setVisibility(View.GONE); fLayout2.setVisibility(View.VISIBLE); but the problem is the image from the first player (paused) is always there although the audio from the other player can be heard. Is that because I added SurfaceView in xml but not in java code? – Shalina Hu Mar 21 '15 at 00:35
  • See my update above. If you see paused video and hear the opposite video, then you likely have the hide state an play state out of sync. – Gary Bak Mar 21 '15 at 00:53
  • Thanks a lot. I did try the same thing before you post (I missed the setting INVISIBLE in l2 earlier). However, still not working (same as before). I tried to call l1.invalidate() ... to force a layout redraw but no impact. Must something I missed. Still debugging (trying to sync the state...) – Shalina Hu Mar 21 '15 at 02:39
  • What exactly are you displaying in the SurfaceView? Video clips, camera data or RTP data? – Gary Bak Mar 21 '15 at 03:23
0

Thanks, Gary. Your notes gave me some idea. I think the two-layout plus visibility setting is the right way to go but there must be a bug in Android as the invisible setting not functioning for SurfaceView (I have tried many. I will check this later).

Anyway, I follow the two-layout set up idea and use media player setDisplay() to change the view. It is working. Basically I did this,

// Create a third dummy view
SurfaceView svDummy = new SurfaceView(...);

// Add to layout 2
l2.addView(svDummy);

// get holders
mHolder1 = sv1.getHolder();
mHolder2 = sv2.getHolder();
mHolderDummy = svDummy.getHolder();

MediaPlayer mMediaPlayerA;
MediaPlayer mMediaPlayerB;

Note that layout 1 is on top (according to the sequence in FrameLayout definition in the xml file) and is used as the active view all the time. I first set mMediaPlayerA on sv1 and pause mMediaPlayerB. Then, I alternatively set this.

mMediaPlayerA.pause();
mMediaPlayerA.setDisplay(svDummyHolder); // This is needed. Otherwise, does not work
mMediaPlayerB.setDisplay(sv1Holder);     // sv1Holder is the active one all the time
mMediaPlayerA.setDisplay(sv2Holder);
mMediaPlayerB.start();

...
mMediaPlayerB.pause();
mMediaPlayerB.setDisplay(svDummyHolder); // This is needed. Otherwise, does not work
mMediaPlayerA.setDisplay(sv1Holder);     // sv1Holder is the active one all the time
mMediaPlayerB.setDisplay(sv2Holder);
mMediaPlayerA.start();

The dummay view is needed. Otherwise, it did not work.

The summary is: to make this work, each media player needs a physical SurfaceView (not shared by others) and each SurfaceView needs to be mapped to a physical layout.

Again, thanks.

Shalina Hu
  • 31
  • 1
  • 4
  • Forgot to mention, you may need to add Thread.sleep(a number) before the media player's start(). I am still tweaking. – Shalina Hu Mar 21 '15 at 14:06