I use a SurfaceView for displaying a video in my app, and it is released when I change the content view to somewhere else. My question is quite easy (I guess):
When I want to switch back to the view with the video, I have to provide a new SurfaceView to the player, since an error message tells me that the surface has been released.
Can I somehow simply re-initiate the SurfaceView I defined in my layout.xml to reuse it?
Or does someone have a better idea to pause a video in a MediaPlayer, display an image, and switch back to the video without destroying the SurfaceView?
Cheers!
Related
Is there a way to have a media file (audio/video) running in a cardview layout? I want to have a video preview of the file inside a card layout, when the user clicks on the card the video/audio is taken fullscreen and played, just like Facebook's feed.
In order to get that kind of functionality you have to solve a few problems:
You cannot use VideoView in a list because it is extending SurfaceView, and if playback is on and user starts scrolling, the visual effect will look like video is trying to catch the scroll. So you need a special VideoView that is based on something else, for example TextureView.
Managing video player state:
in order to start/stop playback we need to call a few methods of MediaPlayer.class:
setDataSource()
prepare()
start()
stop()
reset()
release()
These methods are direct calls to hardware and it may take some time before hardware will respond. So we cannot call it in UI thread. It will block it for more than 16 milliseconds, so user will see a lagging scrolled list. We have to call it from a background thread.
You need to track in run time which view on the screen is active and this view should be playing.
I've created an opensource project called VideoPlayerManager.
It is thoroughly documented and some basic flows are handled in the demo application. It is not ready for production but if you need some reference of how to get this kind of functionality, you can find it there.
P.S. Regarding CardView: it is a regular view. You can put a video player into it and get video playback in CardView.
On Video players such as Youtube, I often see that when the user taps on the video view a sort of overlay shows up where the user can choose actions like: “share”, “add to playlist”, “pause”, etc. Basically it’s whatever the developer wants. The developer seems to be able to choose what the icons are, where they go, etc.
I would like to know how it’s done. For example, are they using a VideoView with an overlay? Are they using a FrameLayout with a VideoView and a RelativeLayout on top of the VideoView? I just need some advice in the right direction as I don’t know where to start. Thanks. For simplicity, I am looking to add a Youtube style video player to my activity. And by Youtube style, I am referring to the aforementioned interactions.
I would like to know how it’s done
I am sure that the implementation varies widely.
For example, are they using a VideoView with an overlay?
AFAIK, few professional-grade apps use VideoView, simply because VideoView offers little in the way of events or control. More likely, they are using something else backed by MediaPlayer or third-party media libraries (e.g., ExoPlayer).
Are they using a FrameLayout with a VideoView and a RelativeLayout on top of the VideoView?
No, because that would be two VideoView widgets. However, whatever their video surface is probably resides in a RelativeLayout or FrameLayout, with the overlay as another child of that same container, though I am sure that there are other approaches.
You are welcome to use uiautomatorviewer to try to learn more about the view hierarchy of particular apps of interest.
Phone only with Android 4.0+ and no other third party libraries.
Application uses Navigation Tab of the ActionBar. One of the tab contains the stock VideoView control from ICS streaming live video from a source. I want to have the VideoView keep playing when user switch tabs to view information (call it InformationView).
On a tablet, I don't have this issue because the screen size is bigger and I make VideoView always on screen.
On a phone, screen is smaller therefore tab must be used.
I understand that VideoView probably depends on a visible surface in order to draw the video frame. When user switch tabs, the surface isn't available to VideoView therefore it automatically stops.
I can probably work around this by using a big scrollview that contains both InformationView and VideoView.
Is there any way to force it keep playing (maybe by drawing to an invisible surface) or is there a third party library that mimic the 'tab' behavior by using a giant scrollview so I don't have to write more code?
Note this isn't the same as multiple VideoViews problem which described here: One videoview blocked by another videoview
OK the solution is to hide the fragment that contains the VideoView when switching tabs, hence there is always a 'surface' video view can draw to.
You can custom VideoView same default but that's different you should control holder surface, oncreatSurface, onchangeSurface().
A better implementation of this concept would be not to use the stock VideoView widget, which is really just a marrying together of a SurfaceView and a MediaPlayer, but to divorce these two and use them individually. If your application controls the MediaPlayer directly, is can continue to play the audio track even after the surface disappears.
Making your Activity or Fragment one of the SurfaceHolder.Callback instances attached to the SurfaceView will allow you to know when the surface is or is not available for drawing. The MediaPlayer methods setDisplay() and setSurface() would be then used in your application to attach and detach the video surface when it becomes available in the view hierarchy per that callback.
You may also find the source of VideoView helpful (link) in coming up with your own implementation that accomplishes a similar goal.
I'm working on a multimedia video processing application for Android, and I've run into a bit of a problem. I'm using the FragmentPagerAdapter class with a number of different fragments inside for various steps of video processing.
My first Fragment contains a SurfaceView and a MediaPlayer that feeds it, along with various playback controls. My problem happens when I swipe from fragment 1 (with the SurfaceView) to fragment 2 (empty at the moment). If I haven't yet called start(), nothing unusual happens, and I'm able to swipe between fragments normally. Once I call start() however, the entire screen starts flashing on and off when I swipe to the next Fragment, even if I've put the MediaPlayer in the idle state and it's not feeding frames to SurfaceView. The only thing that stops this is destroying the surface along with the containing view by swiping to the third Fragment so the FragmentPagerAdapter destroys Fragment one, or exiting the application via the home or back button so the view is destroyed.
I can't for the life of me figure out why this is happening, other than that perhaps the SurfaceView rendering thread is somehow interfering with the main UI thread. Nothing unusual appears on LogCat, either, so I'm a bit stuck. I'm running a Galaxy Nexus with android 4.1 as my test hardware.
Any help would be appreciated!
JT
UPDATE: I've managed to find a workaround for now by overriding the setPrimaryItem() method in the FragmentPagerAdapter to call a method that removes the SurfaceView from the hierarchy (using removeView() on its LinearLayout container) when the video player Fragment ceases to be displayed, and then reinstates the SurfaceView when it's active again. There's still a bit of a blink when this happens, unfortunately, so if anyone has additional thoughts, I'd be grateful!
From the Android Developers Blog
This widget[SurfaceView] works by creating a new window placed behind your application’s window. It then punches a hole through your application’s window to reveal the new window.
Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView.
The Solution is to use a TextureView if you're building for 4.0 or above. If youre interested in using a TextureView to display video this thread might be helpful
I have a webview that's playing a video, and I want it to appear behind some other views, but I can't seem to make it happen. I've tried simply just sending the foreground views to the front with bringChildToFront(View v), but no cigar. Any thoughts?
Edit: Some more details: The webview plays a video using flash, and the webview is the size of the entire screen. I have some stuff I want to pop up in front of the video, but they only stay behind the video. They're definitely there, as they receive touch events and stuff, but just hidden away from view by the video.
Since the Flash player will essentially pre-empt any other views in the window, you'll just have to do one better over Flash: use another window on top of the main window.
Android allows you to do this by using the PopupWindow class.