I can't get Flowplayer to automatically play video in a WebView on Android. The video plays fine if the in-HTML play button is pressed, but it won't start by itself. This seems to be Chrome-related since autoplay doesn't work in the Android Chrome browser either. It does work in the stock Android browser and in Chrome for the (Linux) desktop.
I've seen this page that suggests adding a WEBM file to get MP4 content to work, but it didn't help. I've also seen this page that mentions using the new setting setMediaPlaybackRequiresUserGesture(), but that didn't help either.
Has anyone gotten autoplay to work in an Android WebView?
Here is my test code that distills the app down to its essentials.
package com.example.testautovideo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webview = new WebView(this);
setContentView(webview);
webview.setWebChromeClient(new WebChromeClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setLoadsImagesAutomatically(true);
// webview.getSettings().setMediaPlaybackRequiresUserGesture(false); // didn't help
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
webview.loadUrl(THE_URL);
}
}
Here is the source of my web page. The Flowplayer and jQuery calls are to standard installs. The Flowplayer library is the latest free version; the jQuery library is the latest production version.
<!DOCTYPE HTML>
<html>
<head>
<meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1,target-densitydpi=device-dpi'>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta property="ws:skip" value="false" />
<title>Autoplay Test</title>
<link rel="stylesheet" type="text/css" href="src/js/flowplayer/skin/minimalist.css">
<script type="text/javascript" src="src/js/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="src/js/flowplayer/flowplayer.min.js"></script>
<script>
$(document).ready(function(){
function playVideo(){
var player = flowplayer($('#theVideo'));
player.play();
}
setTimeout(playVideo,10);
});
</script>
<style>
body {
margin:0;
padding:0;
background:#000;
}
#wrapper .flowplayer {
width:640px;
height:360px;
}
#wrapper {
width:640px;
height:360px;
background:#000;
margin:30px auto;
}
</style>
</head>
<body>
<div id="wrapper">
<div class="flowplayer" id="theVideo">
<video preload="none" autoplay>
<source type="video/webm" src="video_1.webm">
<source type="video/mp4" src="video_1.mp4">
</video>
</div>
</div>
</body>
</html>
I know links can go stale, but here's a copy of that web page with working Flowplayer and jQuery installs.
The following is an approach that works on all versions of Android down to Honeycomb (API 11), and perhaps earlier. The important part is to dynamically run load() and play() on the video via JavaScript. Even then, it doesn't always work on older versions of Android (with the setMediaPlaybackRequiresUserGesture()
call, which was added in API 17, removed.
The WebView refuses to let the load/play start automatically, but it will let the Android app initiate it. It's desirable for the page itself to be able to determine when the video is started, rather than the app.
Here's what was done to get it all to work. First, a guard condition was put around around the setMediaPlaybackRequiresUserGesture()
call to keep it from being run on pre-Jellybean MR1 devices. Then a small, single-method JavascriptInterface class was added and enabled. That method calls an on-page JavaScript method that loads and plays the page's video. Finally, the web pages were altered to call the exposed method when the video should be started. In the code below, the method is called when page has finished loading and the video is set to loop continuously.
Yes, there's a known security concern with enabling a JavascriptInterface class, but our's only has a single method and that method doesn't do anything other than call back into the calling JavaScipt.
{
...
webView = (WebView) findViewById(id.web);
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
webView.addJavascriptInterface(new JsInterface(), "AndroidApp");
}
class JsInterface {
@JavascriptInterface
public void startVideo() {
Log.v(TAG, "in JsInterface.startVideo()");
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.v(TAG, "in JsInterface.startVideo.run");
webView.loadUrl("javascript:playVideo()");
}
});
}
}
<!DOCTYPE HTML>
<html>
<head>
<meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1,target-densitydpi=device-dpi'>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Autoplay Test</title>
<link rel="stylesheet" type="text/css" href="src/js/flowplayer/skin/minimalist.css">
<script type="text/javascript" src="src/js/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="src/js/flowplayer/flowplayer.min.js"></script>
<script type="text/javascript">
function playVideo(){
var player = flowplayer($('#theVideo'));
player.load('video_1.mp4');
player.bind("finish", function() {
player.play();
});
}
$(document).ready(function(){
AndroidApp.startVideo()
});
</script>
<style>
body {
margin:0;
padding:0;
background:#000;
}
#wrapper .flowplayer {
width:640px;
height:360px;
}
#wrapper {
width:640px;
height:360px;
background:#000;
margin:30px auto;
}
</style>
</head>
<body>
<div id="wrapper">
<div class="flowplayer is-splash" id="theVideo">
<video preload="none">
<source type="video/mp4" src="">
</video>
</div>
</div>
</body>
</html>