Android Custom WebView I have made a custom webview which is used to open a very heavy site in terms of database. The webview uses custom code for uploading files using an upload handler class. I need suggestions on how I can optimize my code for better performance.

Features necessary (current custom webview written below does it all):


The basic functionality is just to load a responsive WordPress website.
Webview should support image uploading features.
mailto: links should open in the default email client.


I am adding the complete main activity page for your reference.

package com.Example.application;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;




import android.annotation.SuppressLint;

public class MainActivity extends Activity  implements OnClickListener {

      final Context context = this;
    private WebView webView;
     private ImageButton btnrefresh;    
     private TextView txtrefresh;
     private Menu optionsMenu;
     private WebChromeClient.CustomViewCallback customViewCallback;
        private View mCustomView;




    @SuppressWarnings("deprecation")
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //define button 
        btnrefresh = (ImageButton) findViewById(R.id.imageButton1);

        btnrefresh.setOnClickListener(this);
        btnrefresh.setVisibility(View.GONE);

        //define textView
        txtrefresh = (TextView)findViewById((R.id.textView1));
        txtrefresh.setVisibility(View.GONE);


        if(isConnected())
        {

            webView = (WebView) findViewById(R.id.webView1);
            webView.getSettings().setJavaScriptEnabled(true);       
               webView.getSettings().setAppCacheEnabled(true);

                webView.getSettings().setRenderPriority(RenderPriority.HIGH);
                webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
                webView.getSettings().setSaveFormData(true);
        //  webView.getSettings().setPluginState(PluginState.ON);
          webView.setWebViewClient(new WebViewClient()
          {
          @Override
          public boolean shouldOverrideUrlLoading(WebView view, String url) {


              if (url.startsWith("mailto:")) {
                  sendEmail(url.substring(7));
                  return true;
              }

              return false;
          }

        });


            initWebView(webView);                         
            webView.loadUrl("http://Example.com/");             

            }


        else
        {
Your code formatting needs a lot of work, I couldn't even read through the code because I kept getting lost. 


Be consistent with your bracing style

pick one and stick to it

Get rid of unnecessary whitespace

too many extra lines

Don't comment out code and leave it there

if you aren't using it, delete it



Then you end up with something like this this

package com.Example.application;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.MailTo;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity  implements OnClickListener {

    final Context context = this;
    private WebView webView;
    private ImageButton btnrefresh;    
    private TextView txtrefresh;
    private Menu optionsMenu;
    private WebChromeClient.CustomViewCallback customViewCallback;
    private View mCustomView;




    @SuppressWarnings("deprecation")
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //define button 
        btnrefresh = (ImageButton) findViewById(R.id.imageButton1);

        btnrefresh.setOnClickListener(this);
        btnrefresh.setVisibility(View.GONE);

        //define textView
        txtrefresh = (TextView)findViewById((R.id.textView1));
        txtrefresh.setVisibility(View.GONE);


        if(isConnected())
        {

            webView = (WebView) findViewById(R.id.webView1);
            webView.getSettings().setJavaScriptEnabled(true);       
            webView.getSettings().setAppCacheEnabled(true);

            webView.getSettings().setRenderPriority(RenderPriority.HIGH);
            webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
            webView.getSettings().setSaveFormData(true);
            webView.setWebViewClient(new WebViewClient()
            {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    if (url.startsWith("mailto:")) {
                        sendEmail(url.substring(7));
                        return true;
                    }
                    return false;
                }
            });

            initWebView(webView);                         
            webView.loadUrl("http://Example.com/");             
        }
        else
        {
            RelativeLayout rel = (RelativeLayout)findViewById(R.id.relativelayout1);
            rel.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v){
                    refresh();
                }
            });
            btnrefresh.setVisibility(View.VISIBLE); 
            txtrefresh.setVisibility(View.VISIBLE);
            Toast.makeText(getBaseContext(), "No Internet Connection !!", Toast.LENGTH_SHORT).show();
        }       
    }

    private void sendEmail(String add) {
        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("text/plain");
        i.putExtra(Intent.EXTRA_EMAIL, new String[] { add });
        try {
            startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(MainActivity.this,
                "There are no email clients installed.", Toast.LENGTH_SHORT)
                .show();
        }

    }

    public boolean onCreateOptionsMenu(Menu menu) {
        this.optionsMenu = menu;
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_activity_actions, menu);
        return super.onCreateOptionsMenu(menu);
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.airport_menuRefresh:
                webView.reload();
                Toast.makeText(getBaseContext(), "Refeshing...", Toast.LENGTH_SHORT).show();
                // Complete with your code
                return true;
            case R.id.goBack:
                if(webView.canGoBack()) {
                    webView.goBack();
                }
                return true;
            case R.id.goForward:
                if(webView.canGoForward()) {
                    webView.goForward();
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public void refresh()
    {
        if (isConnected()) {
            btnrefresh.setVisibility(View.GONE);
            txtrefresh.setVisibility(View.GONE);
            webView = (WebView) findViewById(R.id.webView1);

            webView.setWebViewClient(new WebViewClient()
            {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    if (url.startsWith("mailto:")) {
                        sendEmail(url.substring(7));
                        return true;
                    }
                    return false;
                }

            });
            initWebView(webView);       
            webView.loadUrl("http://Example.com/");         

            Toast.makeText(getBaseContext(), "Connected !!", Toast.LENGTH_LONG).show();
            Toast.makeText(getBaseContext(), "Loading....", Toast.LENGTH_SHORT).show();
            Toast.makeText(getBaseContext(), "Please wait....", Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(getBaseContext(), "No Internet Connection !!", Toast.LENGTH_SHORT).show();
        }       
    }



    public boolean isConnected(){
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null &amp;&amp; networkInfo.isConnected())
        {
            return true;
        }
        else                    
            return false;    
        }
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if ((keyCode == KeyEvent.KEYCODE_BACK)) {
                AlertDialog.Builder alertbox = new AlertDialog.Builder(MainActivity.this);

                alertbox.setTitle("Do You Want To Exit ?");
                alertbox.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface arg0, int arg1) { 
                        // finish used for destroyed activity
                        exit();
                    }
                });

                alertbox.setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface arg0, int arg1) {
                        // Nothing will be happened when clicked on no button 
                        // of Dialog     
                    }
                });

                alertbox.show();
            }
            return super.onKeyDown(keyCode, event);
        }
        public void exit()
        {
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_HOME);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
        public void onClick(View v) 
        {
            //refresh ImageButton function
            if (v == btnrefresh) 
            {
                refresh();
            }
        }

        private final static Object methodInvoke(Object obj, String method, Class&lt;?&gt;[] parameterTypes, Object[] args) {
            try {
                Method m = obj.getClass().getMethod(method, new Class[] { boolean.class });
                m.invoke(obj, args);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        private void initWebView(WebView webView) {
            WebSettings settings = webView.getSettings();

            settings.setJavaScriptEnabled(true);
            settings.setAllowFileAccess(true);
            settings.setDomStorageEnabled(true);
            settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
            settings.setLoadWithOverviewMode(true);
            settings.setUseWideViewPort(true);
            settings.setRenderPriority(RenderPriority.HIGH);

            methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
            methodInvoke(settings, "setPluginState", new Class[] { PluginState.class }, new Object[] { PluginState.ON });
            methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
            methodInvoke(settings, "setAllowUniversalAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });
            methodInvoke(settings, "setAllowFileAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });

            webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
            webView.clearHistory();
            webView.clearFormData();
            webView.clearCache(true);
            webView.setWebChromeClient(new MyWebChromeClient());
        }

        UploadHandler mUploadHandler;
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
            if (requestCode == Controller.FILE_SELECTED) {
                // Chose a file from the file picker.
                if (mUploadHandler != null) {
                    mUploadHandler.onResult(resultCode, intent);
                }
            }
            super.onActivityResult(requestCode, resultCode, intent);
        }

        @SuppressLint("NewApi")
        class MyWebChromeClient extends WebChromeClient {
            public MyWebChromeClient() {

            }
            @SuppressLint("NewApi")
            private String getTitleFromUrl(String url) {
                String title = url;
                try {
                    URL urlObj = new URL(url);
                    String host = urlObj.getHost();
                    if (host != null &amp;&amp; !host.isEmpty()) {
                        return urlObj.getProtocol() + "://" + host;
                    }
                    if (url.startsWith("file:")) {
                        String fileName = urlObj.getFile();
                        if (fileName != null &amp;&amp; !fileName.isEmpty()) {
                            return fileName;
                        }
                    }
                } catch (Exception e) {
                    // ignore
                }

                return title;
            }

            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                String newTitle = getTitleFromUrl(url);

                new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        result.confirm();
                    }
                }).setCancelable(false).create().show();
                return true;
                // return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {

                String newTitle = getTitleFromUrl(url);

                new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        result.confirm();
                    }
                }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        result.cancel();
                    }
                }).setCancelable(false).create().show();
                return true;

                // return super.onJsConfirm(view, url, message, result);
            }

            // Android 2.x
            public void openFileChooser(ValueCallback&lt;Uri&gt; uploadMsg) {
                openFileChooser(uploadMsg, "");
            }

            // Android 3.0
            public void openFileChooser(ValueCallback&lt;Uri&gt; uploadMsg, String acceptType) {
                openFileChooser(uploadMsg, "", "filesystem");
            }

            // Android 4.1
            public void openFileChooser(ValueCallback&lt;Uri&gt; uploadMsg, String acceptType, String capture) {
                mUploadHandler = new UploadHandler(new Controller());
                mUploadHandler.openFileChooser(uploadMsg, acceptType, capture);
            }
        };

        class Controller {
            final static int FILE_SELECTED = 4;

            Activity getActivity() {
                return MainActivity.this;
            }
        }


        class UploadHandler {
            /*
            * The Object used to inform the WebView of the file to upload.
            */
            private ValueCallback&lt;Uri&gt; mUploadMessage;
            private String mCameraFilePath;
            private boolean mHandled;
            private boolean mCaughtActivityNotFoundException;
            private Controller mController;
            public UploadHandler(Controller controller) {
                mController = controller;
            }
            String getFilePath() {
                return mCameraFilePath;
            }
            boolean handled() {
                return mHandled;
            }
            void onResult(int resultCode, Intent intent) {
                if (resultCode == Activity.RESULT_CANCELED &amp;&amp; mCaughtActivityNotFoundException) {
                    // Couldn't resolve an activity, we are going to try again so skip
                    // this result.
                    mCaughtActivityNotFoundException = false;
                    return;
                }
                Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
                        : intent.getData();
                // As we ask the camera to save the result of the user taking
                // a picture, the camera application does not return anything other
                // than RESULT_OK. So we need to check whether the file we expected
                // was written to disk in the in the case that we
                // did not get an intent returned but did get a RESULT_OK. If it was,
                // we assume that this result has came back from the camera.
                if (result == null &amp;&amp; intent == null &amp;&amp; resultCode == Activity.RESULT_OK) {
                    File cameraFile = new File(mCameraFilePath);
                    if (cameraFile.exists()) {
                        result = Uri.fromFile(cameraFile);
                        // Broadcast to the media scanner that we have a new photo
                        // so it will be added into the gallery for the user.
                        mController.getActivity().sendBroadcast(
                                new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                    }
                }
                mUploadMessage.onReceiveValue(result);
                mHandled = true;
                mCaughtActivityNotFoundException = false;
            }
            void openFileChooser(ValueCallback&lt;Uri&gt; uploadMsg, String acceptType, String capture) {
                final String imageMimeType = "image/*";
                final String videoMimeType = "video/*";
                final String audioMimeType = "audio/*";
                final String mediaSourceKey = "capture";
                final String mediaSourceValueCamera = "camera";
                final String mediaSourceValueFileSystem = "filesystem";
                final String mediaSourceValueCamcorder = "camcorder";
                final String mediaSourceValueMicrophone = "microphone";
                // According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
                // or 'microphone' and the default value should be 'filesystem'.
                String mediaSource = mediaSourceValueFileSystem;
                if (mUploadMessage != null) {
                    // Already a file picker operation in progress.
                    return;
                }
                mUploadMessage = uploadMsg;
                // Parse the accept type.
                String params[] = acceptType.split(";");
                String mimeType = params[0];
                if (capture.length() &gt; 0) {
                    mediaSource = capture;
                }
                if (capture.equals(mediaSourceValueFileSystem)) {
                    // To maintain backwards compatibility with the previous implementation
                    // of the media capture API, if the value of the 'capture' attribute is
                    // "filesystem", we should examine the accept-type for a MIME type that
                    // may specify a different capture value.
                    for (String p : params) {
                        String[] keyValue = p.split("=");
                        if (keyValue.length == 2) {
                            // Process key=value parameters.
                            if (mediaSourceKey.equals(keyValue[0])) {
                                mediaSource = keyValue[1];
                            }
                        }
                    }
                }
                //Ensure it is not still set from a previous upload.
                mCameraFilePath = null;
                if (mimeType.equals(imageMimeType)) {
                    if (mediaSource.equals(mediaSourceValueCamera)) {
                        // Specified 'image/*' and requested the camera, so go ahead and launch the
                        // camera directly.
                        startActivity(createCameraIntent());
                        return;
                    } else {
                        // Specified just 'image/*', capture=filesystem, or an invalid capture parameter.
                        // In all these cases we show a traditional picker filetered on accept type
                        // so launch an intent for both the Camera and image/* OPENABLE.
                        Intent chooser = createChooserIntent(createCameraIntent());
                        chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
                        startActivity(chooser);
                        return;
                    }
                } else if (mimeType.equals(videoMimeType)) {
                    if (mediaSource.equals(mediaSourceValueCamcorder)) {
                        // Specified 'video/*' and requested the camcorder, so go ahead and launch the
                        // camcorder directly.
                        startActivity(createCamcorderIntent());
                        return;
                } else {
                        // Specified just 'video/*', capture=filesystem or an invalid capture parameter.
                        // In all these cases we show an intent for the traditional file picker, filtered
                        // on accept type so launch an intent for both camcorder and video/* OPENABLE.
                        Intent chooser = createChooserIntent(createCamcorderIntent());
                        chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
                        startActivity(chooser);
                        return;
                    }
                } else if (mimeType.equals(audioMimeType)) {
                    if (mediaSource.equals(mediaSourceValueMicrophone)) {
                        // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
                        // recorder.
                        startActivity(createSoundRecorderIntent());
                        return;
                    } else {
                        // Specified just 'audio/*',  capture=filesystem of an invalid capture parameter.
                        // In all these cases so go ahead and launch an intent for both the sound
                        // recorder and audio/* OPENABLE.
                        Intent chooser = createChooserIntent(createSoundRecorderIntent());
                        chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
                        startActivity(chooser);
                        return;
                    }
                }
                // No special handling based on the accept type was necessary, so trigger the default
                // file upload chooser.
                startActivity(createDefaultOpenableIntent());
            }
            private void startActivity(Intent intent) {
                try {
                    mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
                } catch (ActivityNotFoundException e) {
                    // No installed app was able to handle the intent that
                    // we sent, so fallback to the default file upload control.
                    try {
                        mCaughtActivityNotFoundException = true;
                        mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
                                Controller.FILE_SELECTED);
                    } catch (ActivityNotFoundException e2) {
                        // Nothing can return us a file, so file upload is effectively disabled.
                        Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
                                Toast.LENGTH_LONG).show();
                    }
                }
            }
            private Intent createDefaultOpenableIntent() {
                // Create and return a chooser with the default OPENABLE
                // actions including the camera, camcorder and sound
                // recorder where available.
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
                        createSoundRecorderIntent());
                chooser.putExtra(Intent.EXTRA_INTENT, i);
                return chooser;
            }
            private Intent createChooserIntent(Intent... intents) {
                Intent chooser = new Intent(Intent.ACTION_CHOOSER);
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
                chooser.putExtra(Intent.EXTRA_TITLE,
                        mController.getActivity().getResources()
                                .getString(R.string.choose_upload));
                return chooser;
            }
            private Intent createOpenableIntent(String type) {
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType(type);
                return i;
            }
            private Intent createCameraIntent() {
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File externalDataDir = Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_DCIM);
                File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
                        File.separator + "browser-photos");
                cameraDataDir.mkdirs();
                mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
                        System.currentTimeMillis() + ".jpg";
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
                return cameraIntent;
            }
            private Intent createCamcorderIntent() {
                return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            }
            private Intent createSoundRecorderIntent() {
                return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
            }
        }
    }


But when I had done all this I saw that you had things like this.


webView.loadUrl("http://Example.com/");

// Complete with your code

webView.loadUrl("http://Example.com/");



These tell me that this isn't code that you have written yourself.