I am building a cross-platform mobile app using Cordova (PhoneGap 3.0.0-0.14.4), with Android as one of the target platforms.
A (major, but not only) part of the functionality of the app is playing video.
I have chosen the html5 <video>
tag as the preferred method of implementing the video player.
The videos are hosted on Vimeo.
The app is implemented as a single html document, where navigation is achieved by altering the content using javascript.
The video tag I used looks like:
<video autoplay controls id="videotag">
<source id="videosrc" src="http://player.vimeo.com/external/..."/>
Din apparat stöder inte denna video.
</video>
Getting the video to be playable worked out of the box just by adding the video tag to the html. On a HTC One mini (Android 4.3) this solution worked without problems. On a Samsung Galaxy S4 mini (Android 4.2.2) the video also plays, but another problem occurs: The video is being buffered by a MediaPlayer component, and this buffering never stops. The log is filled by the following messages, repeated indefinitely:
01-25 13:45:36.698: V/MediaPlayer(2814): message received msg=3, ext1=34, ext2=0
01-25 13:45:36.698: V/MediaPlayer(2814): buffering 34
01-25 13:45:36.698: V/MediaPlayer(2814): callback application
01-25 13:45:36.698: V/MediaPlayer(2814): back from callback
This buffering continues even after playback is stopped, the video tag is removed and the user exits (suspends) the app. Suspending the app does not stop the buffering, but killing the app does. The buffering does not even stop when it reaches 100%, but instead keeps on apparently indefinitely. No sound is playing in the background, but the Internet connection is kept open, the battery drains and the device heats up. This is a showstopper bug for us, as we are not willing to publish an app that causes overheating.
Symptoms similar to the detected problem were also reported by a beta tester on a Samsung Galaxy S3. The problem might be limited to Samsung only, as it does not occur on a HTC device.
It appears that the MediaPlayer component does not receive a message to stop buffering even though the video is no longer needed.
I have tried the following, without success:
- I have removed the video tag entirely from the DOM when done watching.
- I have used javascript to stop the playback by calling pause() on the video element before removal.
- Following HTML5 Video: Force abort of buffering I have tried using javscript to clear the src urls inside the video tag, followed by calling load() on the video tag.
- Based on a comment on the above question, I have tried placing the video tag inside an iframe, which is removed from the DOM when done watching.
- I have tried combining all of the above.
- I have tried having the video tag on a separate page, which is navigated away from. This is a departure from the single-page-with-js model used otherwise.
- I have tried using the Vimeo player through oEmbed, instead of using a html5 video tag directly.
That exhausts the platform-indepent tricks that I have been able to find. There are some approaches based on native Android code
- Stop Android MediaPlayer automatically launched by webpage within WebView gives a potential solution, but according to a comment by the question author, the accepted solution only stops audio from playing but does not kill the MediaPlayer.
- Android WebView Playing HTML5/h.264/mp4 Video, How to get at the MediaPlayer seems to be a similar problem, but with a custom webview instead of cordova. I don't know how to attempt to apply this to cordova.
I am looking for any solution to the problem that allows video to be played without causing overheating. This ought to be a problem that other people have needed to solve, so hopefully there is a cordova plugin that already solves the problem. Is there such a plugin? If there is not, is either of the two Android-native approaches mentioned above implementable in cordova, and would they solve the problem?
A potential workaround would be to kill the app whenever it is suspended. This is ugly and not according to Android guidelines. What is the least ugly way of achieving this?