Android WebView analysis and collation

Keywords: Android Javascript network encoding

Primitive simple usage

Add WebView to the layout file

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

Load WebView with LoadUrl() method

WebView myWebView = (WebView) findViewById(R.id.webview);
// If in the loadUrl() method, the Web page generates an exception and does not throw it into our app
myWebView.loadUrl("http://www.example.com");

Finally, don't forget to add permissions

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

Open System Browser

 * Uri uri = Uri.parse("https://www.example.com");
 * Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 * startActivity(intent);

Common methods of WebView

  • public void onPause () pauses processes that can be paused as much as possible, such as animation, positioning, but JavaScript calls cannot be paused.
  • Public void on Resume () restores from the pause state.
  • Public void pause Timers () stops drawing, element parsing, JavaScript execution, etc. of all (not just the current WebView) webViews in the application. Calling this method when the application is paused can effectively reduce CPU power consumption.
  • public void resumeTimers () restores all WebView layout,parsing,JavaScript timers, etc.
  • public void destroy () destroys the internal state of WebView, and when this method is invoked, WebView will no longer perform any operations. Before invoking this method, you need to remove the WebView from the view system (such as Activity) remove View, because the WebView holds the context reference of the view system at the time of construction.
  • Whether the public boolean canGoBack ()WebView has a history of fallback.
  • Whether the public boolean canGoForward ()WebView has a history to move forward.
  • public void goBack () falls back to the previous history page of this WebView.
  • public void goForward () advances to the previous page in the history. Contrast the Forward Button of Web Browser.
  • Public void go Back OrForward (int steps) goes backward or forward, where steps are positive and negative.
  • public void clearCache (boolean includeDiskFiles) clears all WebView caches in the application
  • public void clearHistory () notifies WebView to clear history
  • Page Up (boolean top): Slide the page displayed by WebView to the top.
  • Page Down (boolean bottom): Slide the page displayed by WebView to the bottom.
// It is common to let the return key go back in the page rather than exit the page directly.
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { 
        mWebView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Three Common Classes

WebSettings

Used to configure and manage WebView

//Declare the WebSettings subclass, and if WebView has destroy, calling the WebSettings method throws IllegalStateException
WebSettings webSettings = webView.getSettings();

//If you want to interact with Javascript in the pages you visit, webview must set up support for Javascript
webSettings.setJavaScriptEnabled(true);  

//Support plugins
webSettings.setPluginsEnabled(true); 

//Set up an adaptive screen for both
webSettings.setUseWideViewPort(true); //Adjust the image to the appropriate size for webview 
webSettings.setLoadWithOverviewMode(true); // Scale to screen size

//Zoom operation
webSettings.setSupportZoom(true); //Support zooming, default to true. That's the premise below.
webSettings.setBuiltInZoomControls(true); //Set the built-in zoom control. If false, the WebView is not scalable
webSettings.setDisplayZoomControls(false); //Hide native zoom controls

//Other details
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //If the network is available, it can be loaded on the network. Otherwise, the cache can be used. By changing the constant value, it can be adjusted to only load on the network or only load on the cache. 
webSettings.setAllowFileAccess(true); //Setting Accessible Files 
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //Support for opening new windows through JS 
webSettings.setLoadsImagesAutomatically(true); //Support automatic loading of pictures
webSettings.setDefaultTextEncodingName("utf-8");//Setting the encoding format

// Setting page font size
setTextZoom (int textZoom) //textZoom default size is 100
// Set whether navigation is supported
setGeolocationEnabled(boolean flag)

// A Conventional Method of Setting Cache Mode and Cache Address
 File cacheFile = this.getApplicationContext().getCacheDir();
 if (cacheFile != null) {
     // This method should only be called once, and repeated calls will be ignored.
     mWebView.getSettings().setAppCachePath(cacheFile.getAbsolutePath());
 }
 /**
  * Setting Cache Loading Mode
  * LOAD_DEFAULT(Default value: If the cache is available and does not expire, use it or load it from the network
  * LOAD_NO_CACHE: Loading from the network
  * LOAD_CACHE_ELSE_NETWORK: If the cache is available, load it, even if it has expired, otherwise load it from the network
  * LOAD_CACHE_ONLY: Do not use the network, only load the cache, even if the cache is not available, do not load the network
  */
 int type = AppUtil.getNetWorkType(this);
 switch (type) {
     case AppUtil.NETWORKTYPE_4G:
     case AppUtil.NETWORKTYPE_WIFI:
         mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
         break;
     default:
         mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
         break;
 }

WebViewClient class

Handling various notification and request events, it is invoked when what happens affects the rendering of the content (for example, errors or form submissions), and it can also be used here to intercept URL loading.

  • WebResourceResponse Should InterceptRequest (WebView view, WebResourceRequest request): When WebView needs to request some data, this method can intercept the request to inform app and allow app itself to return a data instead of the data we were supposed to load.
  • Boolean Should Override Url Loading (WebView view, WebResourceRequest request): When we do not provide WebView Client to WebView, WebView will ask Activity Manager for a suitable processor to load the URL (such as the browser that comes with the system), which is usually not what we want to see. So we need to provide a WebViewClient to WebView, and rewrite the method to return true to inform WebView url that the loading is in app, and return false to indicate that the current app processes the url. At this time, we can access web pages in app.

  • OnReceived SslError (WebView view, SslErrorHandler, SslError error): This method is called back when a WebView loading a resource causes an SSL error, when WebView either executes handler.cancel() to cancel the load or executes handler.proceed() to continue loading (default is cancel). It is important to note that this decision may be retained and the same operation performed when an SSL error is encountered again in the future.

  • OnReceived HttpError (WebView view, WebResourceRequest request, WebResourceResponse errorResponse): The previous method mentioned that onReceived Error will not be called back when the server returns the error code, so what should we do when we need to capture HTTP ERROR and operate accordingly? API23 introduced this method. This method calls back when the server returns an HTTP ERROR and its status code >= 400. The scope of this method is not limited to the Main Frame. Any loading of resources will cause HTTP ERROR callbacks, so we should also perform as few operations as possible in this method, only necessary error handling, etc.

  • OnPage Finished (WebView view, String url): This method is called only once when WebView completes a page loading (also only when Main frame loading). We can turn off loading animation and do other operations at this time. Special note: JS code calls must be invoked after onPageFinished () callback, otherwise they will not be invoked.

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    // If the link is not a regular url, try to open it using the system browser
    if (URLUtil.isNetworkUrl(url)) {
        view.loadUrl(url);
    } else {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        PackageManager pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
        if (activities.size() > 0) {
            startActivity(intent);
        }
    }

    return true;
}

// By default, webView does not process https requests. The page displays blank space. The following settings are required:
webView.setWebViewClient(new WebViewClient() {    
        @Override    
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {    
            handler.proceed();    //Represents waiting for certificate response to continue requesting
        // handler.cancel(); // means suspended connection by default
        // handler.handleMessage(null); // Can do other processing
        }    
    }); 

WebChromeClient class

If WebViewClient is the "Minister of Home Affairs" who helps WebView deal with various notifications and requests, then WebChrome Client is the "Minister of Foreign Affairs" who assists WebView in dealing with Javascript dialog boxes, website icons, website title s, loading progress and other partial external events.

  • OnProgressChanged (WebView view, int new progress): Callbacks are used to inform the main program of the current page loading progress when the page loading progress changes.

  • OnReceived Title (WebView view, String title): Used to receive the title of the web page, we can set the title of the page to the Toolbar here.

  • boolean onJsAlert(WebView view, String url, String message, JsResult result): Handles the Alert dialog box in Javascript

  • OnShow CustomView (View view, WebChromeClient. CustomViewCallback callback): This method calls back when the current page enters full-screen mode. The main program must provide a custom View containing the current web content (video or Something).

  • onHideCustomView(): This method calls back when the current page exits full-screen mode, at which time the main program should hide the View that appeared before the show.

// gei WebView adds a progress bar
@Override
public void onProgressChanged(WebView view, int newProgress) {
    if (newProgress < 100) {
        progress.setVisibility(View.VISIBLE);
        progress.setProgress(newProgress);
    } else {
        progress.setProgress(newProgress);
        progress.setVisibility(View.GONE);
    }
    super.onProgressChanged(view, newProgress);
}
// Set the page title to WebViewActivity
webview.setWebChromeClient(new WebChromeClient(){

    @Override
    public void onReceivedTitle(WebView view, String title) {
       titleview.setText(title);
    }
// Dealing with the need to submit documents in the web page
//For Android  >= 4.1
  public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
      uploadMessage = valueCallback;
      openImageChooserActivity();
  }

  // For Android >= 5.0
  @Override
  public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
      uploadMessageAboveL = filePathCallback;
      openImageChooserActivity();
      return true;
  }

...
// Select files and callbacks in Activity
    private void openImageChooserActivity() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_RESULT_CODE) {
            if (null == uploadMessage && null == uploadMessageAboveL) return;
            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
            if (uploadMessageAboveL != null) {
                onActivityResultAboveL(requestCode, resultCode, data);
            } else if (uploadMessage != null) {
                uploadMessage.onReceiveValue(result);
                uploadMessage = null;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
        if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
            return;
        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (intent != null) {
                String dataString = intent.getDataString();
                ClipData clipData = intent.getClipData();
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        ClipData.Item item = clipData.getItemAt(i);
                        results[i] = item.getUri();
                    }
                }
                if (dataString != null)
                    results = new Uri[]{Uri.parse(dataString)};
            }
        }
        uploadMessageAboveL.onReceiveValue(results);
        uploadMessageAboveL = null;
    }

Interaction between Js and WebView

There are two ways for Android to call JS code:
1. WebView. loadUrl through WebView ("javascript:methodName(parameterValues)";//Applicable to JS methods with no return value
2. Evaluate Javascript (String script, Value Callback resultCallback) // for JS methods with return values through WebView

// Setting permissions to interact with Js
webSettings.setJavaScriptEnabled(true);

try {
    InputStream is = FileUtil.getStream(WebViewActivity.this, "raw://inithtml");
    String js = FileUtil.readStreamString(is, "UTF-8");
    mWebView.loadUrl("javascript:" + js);
} catch (IOException e) {
    e.printStackTrace();
}
// This method does not refresh the page, but loadUrl does the js code to refresh the page.
mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        //Here is the result returned by js
    }
});
}

There are three ways for JS to call Android code:
1. Object mapping through WebView's addJavascriptInterface ()
2. Intercept url by calling back the shouldOverrideUrlLoading () method of WebViewClient
3. Intercept JS dialog alert(), confirm(), prompt () messages via WebChromeClient onJsAlert(), onJsConfirm(), onJsPrompt () method callbacks

// 1. Define native methods for JS calls locally, and methods invoked by JS must be annotated with @JavascriptInterface
@JavascriptInterface
public void show(String s){
    Toast.makeText(getApplication(), s, Toast.LENGTH_SHORT).show();
}

// 2. Mapping JSObject class to JSObjectIn Javascript object in JS by addJavascriptInterface () of WebView
mWebView.addJavascriptInterface(new JSObject(this), "JSObjectInJavascript");

// 3. Write the JS method and call the native method written in the first step
function toastClick(){
    window.android.show("JavaScript called~!");
}

Reference resources
Android: Here's the way you want WebView to interact with JS
Android: The most comprehensive Web view in detail
WebView. Driving Guide

Posted by bassdog65 on Sat, 11 May 2019 22:43:14 -0700