App development in Android is relatively simple and quick thanks to WebView, which allows you to load your custom HTML code or a website. However, WebView has some limitations, including a lack of features such as file download and upload, JavaScript alerts, and HTML5 video support, including YouTube embedding and playing issues.
In this tutorial, we will explore WebView while adding file download, file upload, JavaScript alerts, and HTML5 video support using custom and modified Android Java code. We will also use an example Android project to test these features.
Prerequisites
- Knowledge of Java (Android)
- Understanding of Android Project structure
- Knowledge of HTML and JavaScript
Adding required permissions to AndroidManifest.xml
You need to add Internet access user permissions (android.permission.INTERNET
) in your AndroidManifest.xml to grant permission to access the Internet.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package.name"> ... <uses-permission android:name="android.permission.INTERNET" /> <application ... </manifest>
Running an app without this permission would crash your app repeatedly without a proper error indication.
Creating WebView Activity
Add an empty activity to your project from Android > Empty Activity and add the following XML code to your newly created activity layout file:
... <WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/webView"> </WebView> ...
Once you’ve added the above WebView layout to your main activity, where you will be displaying the HTML pages, the next step is adding the necessary Java code to handle the various events.
Declare the following variables in the main public class:
... WebView webView; ProgressDialog progressDialog; private static ValueCallback<Uri[]> mUploadMessageArr; ...
Define the ProgressDialog after setContentView(…) as:
... progressDialog = new ProgressDialog(YOUR_ACTIVITY_NAME.this); progressDialog.setCancelable(true); progressDialog.setMessage("Loading..."); // you can set your custom message here progressDialog.show(); ...
Define WebView as:
webView = (WebView) findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // true/false to enable/disable JavaScript support webView.getSettings().setUserAgentString(new WebView(this).getSettings().getUserAgentString()); // set default user agent as of Chrome webView.setWebViewClient(new WebViewClient()); // we will override WebViewClient() with custom methods webView.setWebChromeClient(new chromeView()); // we will override WebChromeClient() with custom methods. webView.loadUrl("https://www.google.com"); // website on app launch
Adding download file capability/support:
webView.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { progressDialog.dismiss(); Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); } });
All of the above code except the declaration part should be added within the scope of the onCreate() method.
Overriding WebViewClient (should be written within the main class but outside the scope of the onCreate() method):
You need to override the WebViewClient to open the links within the app instead of opening them in Chrome or your default web browser. By overriding WebViewClient, you can also handle events like onPageStarted(), which is useful for displaying the progress bar or determining when the page has started loading, and onPageFinished(), which fires when the page finishes loading the content and allows you to hide the progress bar. onReceivedError() is very useful, especially when you want to display custom “404” messages or inform the user that there are Internet issues that need to be fixed, as well as hide the progress bar if any error occurs in loading the page.
class WebViewClient extends android.webkit.WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return super.shouldOverrideUrlLoading(view, request); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressDialog.show(); // showing the progress bar once the page has started loading } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); progressDialog.dismiss(); // hide the progress bar once the page has loaded } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); webView.loadData("","text/html","utf-8"); // replace the default error page with plain content progressDialog.dismiss(); // hide the progress bar on error in loading Toast.makeText(getApplicationContext(),"Internet issue",Toast.LENGTH_SHORT).show(); } }
Adding upload file support by overriding WebChromeClient (should be written within the main class but outside the scope of the onCreate() method):
By overriding WebChromeClient(), you not only add JavaScript alert support but also file upload support with the help of startFileChooserIntent() and onActivityResult().
public class chromeView extends WebChromeClient { @SuppressLint("NewApi") @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) { return YOUR_ACTIVITY_NAME.this.startFileChooserIntent(valueCallback, fileChooserParams.createIntent()); } } @SuppressLint({"NewApi", "RestrictedApi"}) public boolean startFileChooserIntent(ValueCallback<Uri[]> valueCallback, Intent intent) { if (mUploadMessageArr != null) { mUploadMessageArr.onReceiveValue(null); mUploadMessageArr = null; } mUploadMessageArr = valueCallback; try { startActivityForResult(intent, 1001, new Bundle()); return true; } catch (Throwable valueCallback2) { valueCallback2.printStackTrace(); if (mUploadMessageArr != null) { mUploadMessageArr.onReceiveValue(null); mUploadMessageArr = null; } return false; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1001 && Build.VERSION.SDK_INT >= 21) { mUploadMessageArr.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data)); mUploadMessageArr = null; } } }
Handling the back button press:
You may be looking for functionality that can take the user to the previous page, and if there is no previous page, then close the current activity. Well, you can achieve this by overriding the onBackPressed() method as follows:
@Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { finish(); } }
To add HTML5 audio and video play support, including YouTube, you need to enable hardware acceleration by adding the following code in your Manifest.xml file.
<application android:hardwareAccelerated="true">