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:
That exhausts the platform-indepent tricks that I have been able to find. There are some approaches based on native Android code
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?
After struggling for over a day on something similar, I have found that you can crash the MediaPlayer
inside a WebView
by sending the WebView
to a page with a HTML5 video tag with a bad video url. The example below is a main activity with a valid video tag. If you press play, the MediaPlayer
will take over and start running forever... BUT when you click back or home and leave the app, the onPause()
is triggered and the WebView
is redirected to a page with a bad video url and told to autoplay. Attempting to play crashes the MediaPlayer
and voila! The MediaPlayer
is no more.
package com.test.webviewtest;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = new WebView(this);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
String html = "<video width=\"320\" height=\"240\" controls>" +
"<source src=\"http://www.w3schools.com/html/movie.mp4\" " +
"type=\"video/mp4\"></video>";
webView.loadData(html, "text/html", null);
setContentView(webView);
}
@Override
protected void onPause(){
super.onPause();
// attempt to kill the MediaPlayer here...
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon){
String js = "javascript:document.getElementsByTagName('video')[0].play();";
webView.loadUrl(js);
}
});
String html = "<video width=\"320\" height=\"240\" controls>" +
"<source src=\"http://www.w3schools.com/html/" +
"NOT_A_MOVIE.mp4" +
"\" type=\"video/mp4\"></video>";
webView.loadData(html, "text/html", null);
}
}
Note the logs:
02-26 13:19:13.010 220-25370/? V/MediaPlayerService﹕ [607] notify (0x43a3aeb8, 100, 1, -1004)
02-26 13:19:13.010 25262-25274/com.test.webviewtest V/MediaPlayer﹕ message received msg=100, ext1=1, ext2=-1004
02-26 13:19:13.010 25262-25274/com.test.webviewtest E/MediaPlayer﹕ error (1, -1004)
02-26 13:19:13.010 25262-25274/com.test.webviewtest V/MediaPlayer﹕ callback application
02-26 13:19:13.020 25262-25274/com.test.webviewtest V/MediaPlayer﹕ back from callback
02-26 13:19:13.020 25262-25262/com.test.webviewtest E/MediaPlayer﹕ Error (1,-1004)
And then the blissful silence of no more MediaPlayer
logs...
See Android WebView HTML5 Video Spawns MediaPlayer that lives forever on Samsung S4 [Hacked answer found] for more discussion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With