Monday, October 22, 2012

Partial Support for the Video Tag in PhoneGap Android 2.2.0

Well if you've followed the saga of getting the video tag to work properly in the WebView on Android then you've read my post about why I created the VideoPlayer plugin and it's enhancement. Well in the upcoming PhoneGap 2.2.0 we will have better, but not perfect, support for the video tag thanks to work by Steren Giannini.

In Android 4.x you only need to set the hardwareAccelerated attribute to true in order to get true in-line video tag support on Android.

Unfortunately, in earlier versions of Android this doesn't fix the problem. So instead code has been added to the core of PhoneGap to detect the video tag and handle it better. Sadly, we are unable to play the video in-line but when a users taps on a video tag a full screen video player will be launched. In order to get back to the main app the user need only hit the back button to return to main app screen.

There are a few caveats though. The video tag will only support a single source so it will need to look something like this:
<video poster="http://path.to.my/poster.png" controls>
<source src="http://path.to.my/video.mp4">
</source> />
</video>
Additionally the source url can refer to a video on the internet using the http:// protocol or a local file using the file:// protocol. At this time videos in the assets directory are not support so something like file:///android_asset/www/video.mp4 will not work.

So again, it's not perfect but it is better than nothing. If you are getting tripped up with one of the caveats I described above the VideoPlayer plugin still works.

24 comments:

James said...

Thanks for the helpful post.

I am still struggling to get the video tag to play in my android app. I don't want to use the video plugin as it takes you out of the app and interrupts the user experience.

I have a phonegap project set up in eclipse using cordova 2.2.0

It extends DroidGap.

I am targeting Android 4.0+.

I have tested on several tablets including the Nexus 10 running 4.2

I have turned on hardware acceleration in the AndroidManifest.xml

Is there a way to test if the hardware acceleration is enabled through phonegap? Can we access: View.isHardwareAccelerated()

My poster image loads if I do this:

var video = document.getElementById('testVideo')
video.poster="cover.jpg";

But if I set the source:

video.src = "test.mp4";

I just get a loading video symbol and nothing appears not even the poster image.

I have tried multiple codecs. All play via the browser on the tablet and all play via your video plugin but not via the video tag.

I have also tried loading a video from the internet but get the same problem.

I am really stumped by this and would really appreciate any advice you can offer.

Have you managed to get this to work in a phonegap app?

Is it possible to upload an example?

Thanks in advance.
James

Kim Rasmussen said...

Hi,
This is a good start!
Unfortunatly I need a couple of more things in order for it to work on my app.. So i am back to the Well trusted Plugin..

If you what feedback on it let me know

Keep up the brilliant work
Thanks
Kim

Simon MacDonald said...

@James

Well if you are using Android 4.x then you aren't using our shim which
is only needed in earlier versions of Android. If you have hardware
acceleration turned on correctly then the video tag should work. You
won't be able to play things out of the assets directory but you
should be able to load things off the file system or via http.

What does your html look like?

Petri said...

Simon, thanks for the good work....

However, I'm having some problems with Nexus 7 (4.2.1), playing local videos.

I understand the videos from asset folder are not supported by the latest PhoneGap 2.2.0. Therefore I have implemented a condition which will use the video.js plugin instead. Video.js plugin works fine with 2.2.2 and 4.0.4 devices, but not with 4.2.1.

I'm getting an error:
ERR Playing: file:///android_asset/www/media/la-test-02.mp4
ERR Error: TypeError: Object [object Object] has no method 'exec'

my code:
try {
console.log("Playing: " + path);
window.plugins.videoPlayer.play(path);
} catch (e) {
console.log("ERR Playing: " + path);
console.log("ERR Error: " + e);
}

You mentioned in previous reply, "should be able to load things off the file system or via http"

I would like to try the file system route, but so far had no luck of locating the "file:///android_asset/www/media/la-test-02.mp4" file via file system. I tried using this example: http://docs.phonegap.com/en/2.2.0/cordova_file_file.md.html#FileReader

Any pointers would be appreciated with either solving the "exec" problem or locating the local file via file system.

Simon MacDonald said...

@Petri

If you can't find "exec" then it doesn't sound like PhoneGap has loaded yet. Do other PhoneGap commands work at this point?

The files in /android_asset/www don't actually exist on the file system. They are part of your application bundle.

Petri said...

@Simon, thanks for your reply.

Indeed it seems like other PhoneGap commands are not working either. (I had to create a network check in order to determine this.)

As a matter of fact, the entire deviceready is not fired.

Yet the exact same code works with older Android systems, which makes me wonder what needs to be done differently with 4.2.1, in order to get the PhoneGap stuff loaded up.

So far my search for that has been fruitless.

Petri said...

Just found the info for the problem of "deviceready" not firing on 4.2.1. here. (https://groups.google.com/forum/?fromgroups=#!topic/phonegap/MDYdSSE9ALA)

Simon MacDonald said...

@Petri

So you are good now?

Petri said...

@Simon,

Yes. Everything is working as expected now. Thank you.

I implemented the easy fix which was to lower the target platform from 17 to 16, as indicated in the group post.

R.J. Steinert said...

I have been successful at getting an example of loading a remote video via HTTP but I have had not luck loading a video file on the Android itself. Part of the problem could be me not understanding how the file:/// protocol resolves to the file system. I tried changing the src attribute in my example to file:///test.m4v and then placing test.m4v in almost every directory on my Android device AND every directory in the APK but still no luck.

My example repository is quite simple, would anyone care to fork it in an attempt to show the world that Android can play a video file on an Android device in a WebView?

https://github.com/rjsteinert/HTML5VideoInAndroidWebViewExample/blob/loadLocalFileUsingFileReader/assets/www/index.html

Simon MacDonald said...

@R.J. Steinert

Based upon your github repo you should be using the url file:///android_asset/www/test.m4v to load the video. The next problem you may run into is that the video file codec is not supported.

Simon MacDonald said...

@R.J. Steinert

Oh, except I'm an idiot as it can't read from the Android assets directory. You'll need to copy that file somewhere on the SD card like /mnt/sdcard or load it from a remote http server.

R.J. Steinert said...

@Simon Mac Donal Thank your for the suggestion. I just changed the path to your suggestion and pushed the change to GitHub but still no luck after pushing to an Android device. My guess is that it's not an encoding problem because the same file I'm testing locally (in the repository) is the same file that does work when referenced remotely in the loadRemoteFileFromHTTP branch.

R.J. Steinert said...

Woohoo! Loading from file:///mnt/sdcard/external_sd does the trick.

https://github.com/rjsteinert/HTML5VideoInAndroidWebViewExample/commit/3f7ffb9cca9656cd4286d490e348960e37126c09#L0L9

Is there any way to load files from the APK itself? In order to make the example a self contained thing we would at the moment have to write an install script that puts that test.m4v file on your SD Card. That would be a really ugly solution.

Lastly, the fact that the WebView won't let the source of a video file be relative to the page being viewed is absolutely a shame. Does anyone have any idea when Google is going to drop using Android Browser for WebView in favor of Google Chrome or at least start putting some elbow grease into the existing WebView?

Simon MacDonald said...

@R.J. Steinert

No, there is no way to load the files from the APK. I make mention to that in the post. Yeah, you could check for first run and copy the videos to internal or sdcard to be played.

Investigations are being done on our side to be able to run a ChromeWebView but it still adds 11mb to the app and it's pretty buggy. Talks with google developer advocates have intimated they are working on a ChromeWebView but nothing promised.

R.J. Steinert said...

@ Simon MacDonald Thank you so much for your help on this. I get the feeling that the limitation of not being able to reference a video as a relative link may have been something that was overlooked by the Android team. Would that be a fair guess from what you know? I'm thinking about filing a bug report (https://code.google.com/p/android/issues/).

Simon MacDonald said...

@R.J. Steinert

You could try opening an issue but there are many bugs open against the video tag. You're not going to see traction on any of them on Android 4.x or later.

neil briscombe said...

Hi Simon,

Thanks for all the help and advice you give to everyone. The idea of copying out of the application's package and on to the file system struck me too as a work around.

I think it would be a great if could post a code example code.

Kind regards,

Neil Briscombe.

Simon MacDonald said...

@neil briscombe

Check out the code starting from line 80 of the VideoPlayer plugin for an example.

https://github.com/macdonst/VideoPlayer/blob/master/2.2.0/src/com/phonegap/plugins/video/VideoPlayer.java

Hoxton Sax said...

Thanks for a brilliant plugin! I do have one problem though ... using Phonegap 2.4 and JqueryMobile 1.3 and works perfectly on android tablets that I have tested on (including Mexus 7 and Samsung Tablet 10.1) - but on Samsung Galaxy S3 where video plays full screen by default, there is no back button or close button showing so I can not get the user to return to the app.

The app content is an html video tag - (for iOS then this plays fine) but if the platform is Android then the src is used to play using the VideoPlayer plugin. For tablets then the device still shows the 'back' button allowing user to navigate back to the app during or after playing the video - but this is not visible on Samsung Galaxy S3.

Is there a way to add a 'Close' button to the video player (or 'Back' button) in these cases ?

Any help would be gratefully appreciated - and the VideoPlayer plugin has been a 'life saver' . . many thanks for sharing it !

Simon MacDonald said...

@Hoxton Sax

There is no way to add a close button. I just fire off an intent to play the video and the default video player starts to play. It sounds like the video player on the S3 is typical Samsung bloatware that doesn't take into account the way Android works. There is a similar problem with the default voice recorder on Samsung devices as well. The only way to really fix this is to install another application that can play vidoes on the S3 and select that when the video is supposed to be played.

I hate to sound beaten down but this is why I switched to Nexus devices as it keeps the carrier bloat ware off the phone.

Petri said...

On all android devices, as far as I know, there is a back button.

You usually hit it twice in order to get out of the video app and back to the application the video was started from. That's how it seems to be working with my S2 and Nexus 7 as well as my friend's S3.

Simon MacDonald said...

@Petri

Well the HW back button was removed which may confuse some users. It all depends on how well the video player application UI is designed.

Petri said...

Rather strange. I might have gotten
confused by the HW / SW buttons.

What I consider as back button is the one on right side of the Home (real) button (under the glass but not the screen) (Galaxy S3)

I just tested with S3 and my app which is using the video plugin. Video does automatically play full screen, like in any other android device I have tested. Video player is the one that comes by default with S3.

Yet, the back "button" stays visible, and lit as it still outside of the screen area. I hit it once, and the phone prompts me to hit again in order to close the video player.

With Nexus 7, all the "buttons" are in the screen area, they still stay visible while the video is playing, and again hitting twice the back button, video player quits and I can continue using the application.

Have I missed something obvious?