Android WebView Upload and download support

In Android, app development is pretty easy and fast with WebView which let you load your custom HTML code or the website, but there are certain limitations to the WebView which include lacking features like the file download, file upload, JavaScript alert and HTML5 video support including YouTube.

In this tutorial, we would be exploring WebView ahead while adding file download, file upload, JavaScript alert and HTML5 video support using custom and modified Android Java codes. We would also be using an example Android project to test out 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 users-permissions (android.permission.INTERNET) in your AndroidManifest.xml to grant permission to access the Internet.

<manifest xlmns:android...>
 ...
 <uses-permission android:name="android.permission.INTERNET" />
 <application ...
</manifest>

Running app without this permission would crash your app again and again 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 would 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(CONTEXT); //replace CONTEXT with YOUR_ACTIVITY_NAME.CLASS`
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 would be overriding WebViewClient() with custom methods
webView.setWebChromeClient(new chromeView()); //we would be overriding 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 to be added within the scope of onCreate() method.

Overriding WebViewClient (should be written within the main class but outside the scope of onCreate() method):

You need to override the WebViewClient to open the links within the app instead of opening in Chrome or your default web browser. By overriding WebViewClient. You can also handle the events such as onPagestarted() which is useful when you need to display the Progress bar or find when the page has started loading, onPageFinishied() fires when the page finish loading the content using which you can hide the progress bar. onReceivedError() is very useful especially when you want to display custom “404 messages” or tell the user that there are Internet issues that need to be fixed as well as you can hide the Progress bar if there 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 plan 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 onCreate() method):

By overriding WebChroeClient() you not only add the feature JavaScript alert support but also you can add the 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 BrowserActivity.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 Boolean.parseBoolean(null);
        }
    }
    public void onActivityResult(int i, int i2, Intent intent) {
        if (i == 1001 && Build.VERSION.SDK_INT >= 21) {
            mUploadMessageArr.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(i2, intent));
            mUploadMessageArr = null;
        }
}

Handing on back press button:

You may be looking for the 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:

@Override
    public void onBackPressed() {
        if(webView.canGoBack()){
            webView.goBack();
        } else {
            finish();
        }
}

Adding 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">

You can find the WebView Download and upload sample project by Isrg Rajan on the GitHub