This is my first question on the forums.
I am creating an application that implements a simple webview that loads an html5 page from an SD card.
The application is a presentation of 5 sections, and each section contains some text overlaid on top of a high-definition video for about 2 seconds, which plays in a loop, basically acting as a page with a background video. The application works in full screen mode with an automatic mailbox / column depending on the resolution and orientation of the video.
In Chrome (Windows 7) and Node-Webkit, the application works beautifully, it looks good and stable. On Android 4.0.3 (Galaxy Tab 10.1), it works quite well - the application looks good and stable, although it may not be possible to preload the video: I insert mp4s inside the html page using javascript CreateElement ("video") and setting the attribute pre load to true). On Android 4.1.1 (Medion Lifetab), the video simply does not load, and the application displays a gray window with a video icon. Does anyone know why?
Also, the "canplaythrough" event seems to never fire on tablets (I suppose another error), so I have to use the "loadstart" event, which is not the same, but good enough.
Here's the source (a simple web viewer that loads html5 from external storage)
-------------------------------- activity_main.xml ------------ --- -----------------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/mainLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="top" android:orientation="horizontal" android:background="@null" tools:context=".MainActivity" > <WebView android:id="@+id/webView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:focusable="true" android:scrollbars="none" /> </RelativeLayout>
-------------------------------- AndroidManifest.xml ------------ --- -----------------
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.rr.pe2013" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <application android:hardwareAccelerated="true" android:keepScreenOn="true" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.rr.pe2013.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
-------------------------------- MainActivity.java ------------ --- -----------------
package com.rr.pe2013; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.annotation.SuppressLint; import android.graphics.Color; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.Window; import android.view.WindowManager; import android.webkit.ConsoleMessage; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebSettings; import android.webkit.WebChromeClient; import android.webkit.WebViewClient; import android.widget.Toast; public class MainActivity extends Activity { WebView webView; GestureDetector gestureDetector; @SuppressWarnings("deprecation") @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // data folder located on the sd card String webAppFolder = Environment.getExternalStorageDirectory().getPath() + "/rr/pe2013"; // remove title bar as we already have it in the web app this.requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Point to the content view defined in XML setContentView(R.layout.activity_main); // configure the webview setup in the xml layout webView = (WebView) findViewById(R.id.webView); // webView.clearView(); webView.setFocusable(true); webView.requestFocus(); webView.setBackgroundColor(Color.BLACK); webView.setInitialScale(1); // web view settings WebSettings webSettings = webView.getSettings(); // enable javascript, plugins, dom storage, file access webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setPluginState(WebSettings.PluginState.ON); webSettings.setDomStorageEnabled(true); webSettings.setSaveFormData(false); webSettings.setSavePassword(false); webSettings.setAllowFileAccess(true); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { webSettings.setAllowContentAccess(true); } if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true); } // more settings webSettings.setLoadsImagesAutomatically(true); webSettings.setSupportMultipleWindows(false); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(false); webSettings.setSupportZoom(false); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { webSettings.setMediaPlaybackRequiresUserGesture(false); } if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { webSettings.setBuiltInZoomControls(false); webSettings.setDisplayZoomControls(false); } // webchrome client webView.setWebChromeClient(new WebChromeClient() { // handle javascript alerts @Override public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) { showToast(message); result.confirm(); return true; }; // log console messages @Override public void onConsoleMessage(String message, int lineNumber, String sourceID) { // showToast(sourceID + " [" + lineNumber + "]:\n" + message); } public boolean onConsoleMessage(ConsoleMessage cm) { showToast(cm.sourceId() + " [" + cm.lineNumber() + "]:\n" + cm.message()); return true; } }); // webview client webView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView webView, String url) { } @Override public void onReceivedError(WebView webview, int errorCode, String description, String failingUrl) { // showToast("onReceivedError: " + description); } }); // load the URL String url = "file:///" + webAppFolder + "/index.html"; // from sd card webView.loadUrl(url); } @Override protected void onPause(){ super.onPause(); webView.onPause(); } @Override protected void onResume(){ super.onResume(); webView.onResume(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check if the key event was the Back button and if there history if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { webView.goBack(); return true; } // If it wasn't the Back key or there no web page history, bubble up to the default // system behavior (probably exit the activity) return super.onKeyDown(keyCode, event); } // display an on-screen temporary message public void showToast(String toast, int duration) { Toast.makeText(getApplicationContext(), toast, duration).show(); } public void showToast(String toast) { showToast(toast, Toast.LENGTH_LONG); } }