A while ago I needed to add some video playback functionality to an Android application I’m working on. I had the video files in the assets
directory of the application. I needed to figure out how to get those videos playing on the screen. This turned out to be harder than I originally expected.
The official documentation about media playback mentions that you can use the MediaPlayer
class for video and audio playback. Then it continues explaining only how to playback audio but leaves the reader with no information whatsoever how to actually do video playback.
Turns out there’s a view class called VideoView
. The documentation for that class is equally lacking. So I had to rely on my favourite search engine and go read some stackoverflow. Eventually I needed to go read the Android sources since the links I received from the search engines contained misleading information.
What I learned
So my goal was this: I want to play a video file from the assets
directory. Searching the internets got me some “answers” that either confuse assets with raw resources (the latter have resource identifiers while the former don’t – that’s a big difference) or offer code like this:
SurfaceView videoView = (SurfaceView)findViewById(R.id.myVideoView); SurfaceHolder holder = videoView.getHolder(); MediaPlayer player = new MediaPlayer(); player.setDisplay(holder);
Since VideoView
is inherited from SurfaceView
you can technically do that. The bad news is that you really shouldn’t.
That’s because VideoView
creates its own internal MediaPlayer
instance and uses that. You can’t really inject your own MediaPlayer
instance into VideoView
. This fact I only learned when I went reading the relevant source code (good that it’s open source). In my opinion this is one big omission from the Android documentation.
The code above does get your video playing on the view but none of the functionality that the VideoView
offers works (you could just use a normal SurfaceView
in this case).
If you just want to play your video from start to finish then the above code might actually suit you. But if you want to include for example some buttons for the user to control the video playback – using MediaController
perhaps – then you’ll end up into a dead end.
So, how to really do it?
The thing is, I don’t know 🙁
What I do know is this: since VideoView
uses it’s internal MediaPlayer
, the only way to set the video source is through the interface offered by VideoView
. There are methods that take either a String
(a file path) or a Uri
argument. The MediaPlayer
class would have much more choices to offer – choices that actually make it possible to load a video from the assets – which was my original intention in the first place. But that is no help here.
So, in the end I moved my video files to the res/raw
directory. This has some drawbacks but I’ll have to live with it for now.
3 replies on “Android: how (not) to play video files from assets”
Same story for me! A pity… Thanks.
Same here – stupid isn’t it?
Hey man! I’ve also recently struggled through this over a number of days. I eventually came across a third-party library over here (https://github.com/linsea/UniversalVideoView) that worked quite well, albeit with some caveats.
It seems like this is exactly why some major companies resort to coding their own proprietary solutions for playing videos.