Android WebView and JS pages call each other (4)

WebView should still be used very frequently in current projects.
Personally, I always think HTML5 is a trend. Find something to sum up here.
At the end of this article, there is a very good Html5Activity loading class. If you don't want to see it, you can download it directly.

WebSettings

WebSettings webSettings = mWebView .getSettings();

//Support for gesture focus, user name, password or other input
webview.requestFocusFromTouch();

setJavaScriptEnabled(true);  //Support js
setPluginsEnabled(true);  //Support plug-ins 

webSettings.setRenderPriority(RenderPriority.HIGH);  //Improving the Priority of Rendering

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

setSupportZoom(true);  //Support zooming, default to true. That's the premise below.
setBuiltInZoomControls(true); //Set the built-in zoom control.
//If the above is false, the WebView is not scalable, and nothing can be scaled regardless of the settings.

setDisplayZoomControls(false); //Hide native zoom controls

setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //Support content repositioning  
supportMultipleWindows();  //Multi-window 
setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //Close caching in webview 
setAllowFileAccess(true);  //Setting Accessible Files 
setNeedInitialFocus(true); //Set up nodes for webview when requestFocus is invoked by webview
setJavaScriptCanOpenWindowsAutomatically(true); //Support for opening new windows through JS 
setLoadsImagesAutomatically(true);  //Support automatic loading of pictures
setDefaultTextEncodingName("utf-8");//Setting the encoding format

 

About Caching

Caching mode

LOAD_CACHE_ONLY: Read only local cached data without using the network
LOAD_DEFAULT:(default) Decides whether to retrieve data from the network based on cache-control.
LOAD_NO_CACHE: Do not use caching, only get data from the network.
LOAD_CACHE_ELSE_NETWORK uses the data in the cache whenever it is locally available, whether it expires or no-cache.

Combined use (offline loading):

if (NetStatusUtil.isConnected(getApplicationContext())) {
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//Decide whether to retrieve data from the network based on cache-control.
} else {
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//If there is no network, it is obtained locally, i.e. offline loading.
}

webSettings.setDomStorageEnabled(true); // Turn on the DOM storage API function
webSettings.setDatabaseEnabled(true);   //Turn on the database storage API function
webSettings.setAppCacheEnabled(true);//Open Application Caches

String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(cacheDirPath); //Setting up the Application Caches cache directory

Note: Each Application calls WebSettings.setAppCachePath(), WebSettings.setAppCacheMaxSize() only once.

 

 

Loading mode

Load a web page:
webView.loadUrl("http://www.google.com/");
Loading an html page in the apk package
webView.loadUrl("file:///android_asset/test.html");
How to load an html page locally on the phone:
webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

 

 

WebViewClient

WebViewClient is to help WebView handle various notification and request events.
When opening a web page, the system browser is not called, but displayed in this WebView:

 mWebView.setWebViewClient(new WebViewClient(){
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
          view.loadUrl(url);
      return true;
      }
  });

WebViewClient Method

WebViewClient mWebViewClient = new WebViewClient()
{
    shouldOverrideUrlLoading(WebView view, String url)  Most commonly used, such as the one above.
    //All loads on a web page go through this method, and we can do a lot of things with this function.
    //For example, get url, look at url.contains("add"), and add

    shouldOverrideKeyEvent(WebView view, KeyEvent event)
    //This method can be overridden to handle key events in browsers. 

    onPageStarted(WebView view, String url, Bitmap favicon) 
    //This event is to start loading page calls. We can set up a loading page to tell the user that the program is waiting for the network response. 

    onPageFinished(WebView view, String url)
    //Called at the end of page loading. Similarly, we can turn off the loading bar and switch program actions. 

    onLoadResource(WebView view, String url) 
    // Page resources are called when they are loaded, and each resource (such as a picture) is called once. 

    onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    // (Reporting error messages) 

    doUpdateVisitedHistory(WebView view, String url, boolean isReload)  
    //(Updating of historical records) 

    onFormResubmission(WebView view, Message dontResend, Message resend) 
    //(The application re-requests web page data) 

    onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)
    //(Authorization request for return information) 

    onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) 
    //Rewriting this method allows webview to process https requests.

    onScaleChanged(WebView view, float oldScale, float newScale) 
    // (Called when WebView changes) 

    onUnhandledKeyEvent(WebView view, KeyEvent event) 
    //(Called when the Key event is not loaded) 
}

Set the WebViewClient defined above to WebView:

  webView.setWebViewClient(mWebViewClient);

 

 

WebChromeClient

WebChrome Client is a dialog box that assists WebView to process Javascript, website icon, website title, loading progress, etc.
The code in the method is handled by the Android side itself.

WebChromeClient mWebChromeClient = new WebChromeClient() {


    //Get the loading progress of the page and display it in the TextView control in the upper right corner
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress < 100) {
            String progress = newProgress + "%";
        } else {
        }
    }

    //Get the title in the Web page to set the title in your interface
    //When a load error occurs, such as no network, the title retrieved in onReceive Title is that the page cannot be found.
    //Therefore, it is recommended not to use the captured title when triggering onReceive Error.
    @Override
    public void onReceivedTitle(WebView view, String title) {
        MainActivity.this.setTitle(title);
    }

    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        //
    }

    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
        //
        return true;
    }

    @Override
    public void onCloseWindow(WebView window) {
    }

    //A way to deal with alert pop-up box, html pop-up box
    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        //
        return true;
    }

    //Processing confirm pop-up box
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult 
            result) {
        //
        return true;
    }

    //Handling prompt pop-up box
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        //
        return true;
    }
};

Similarly, set the WebChrome Client defined above to WebView:

  webView.setWebChromeClient(mWebChromeClient);

 

 

Call JS code

  WebSettings webSettings = mWebView .getSettings(); 
  webSettings.setJavaScriptEnabled(true); 

  mWebView.addJavascriptInterface(new InsertObj(), "jsObj");

Above is the premise!!!
Then we implement the above class, which provides four methods with very clear annotations.

class InsertObj extends Object {
    //The method provided to html can be obtained in js by var str = window.jsObj.HtmlcallJava(); and
    @JavascriptInterface
    public String HtmlcallJava() {
        return "Html call Java";
    }

    //The parametric functions provided to html are window. jsObj. Htmlcall Java2 ("IT-homer blog").
    @JavascriptInterface
    public String HtmlcallJava2(final String param) {
        return "Html call Java : " + param;
    }

    //Html provides us with functions
    @JavascriptInterface
    public void JavacallHtml() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //Here is the call method
                mWebView.loadUrl("javascript: showFromHtml()");
                Toast.makeText(Html5Activity.this, "clickBtn", Toast.LENGTH_SHORT).show();
            }
        });
    }

    //The parametric function provided by Html
    @JavascriptInterface
    public void JavacallHtml2(final String param) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl("javascript: showFromHtml2('IT-homer blog')");
                Toast.makeText(Html5Activity.this, "clickBtn2", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

There is a vulnerability in Android calling js:
http://blog.csdn.net/leehong2005/article/details/11808557

 

 

Method of WebView

Forward and backward

goBack()// Back
 goForward()// Forward
 GoBack OrForward (intsteps)// proceeds or falls back to the steps specified in the history, starting with the current index. 
                              If steps are negative, they are backward and positive are forward.

Can GoForward ()// Can we move forward?
Can GoBack ()// / Can I go backwards?

Clear cached data:

clearCache(true);//Clear the cache left by web access, because the kernel cache is global, this method is not only for web view, but also for the entire application.
clearHistory()//Clearing up the history of the current webview access will only allow the webview to access all records in the history except the current access record.
clearFormData()//This api simply clears the form data that is automatically filled, and it does not clear the data that WebView stores locally.

The status of WebView:

onResume() //Activate WebView to be active and can normally execute web page responses
onPause()//When the page loses focus and is switched to the background invisible state, onPause action needs to be executed. The onPause action notifies the kernel to suspend all actions, such as DOM parsing, plugin execution, JavaScript execution.

pauseTimers()//When the application is switched to the background, we use webview, which is not only for the current webview, but also for the whole application. It will suspend the layout, parsing and JavaScript timer of all webviews. Reduce CPU power consumption.
resumeTimers()//Restore pauseTimers action.

destroy()//When the Activity is destroyed and shut down, music or video is still playing. It must be destroyed.

But note:
When WebView calls destory, WebView is still bound to Activity. This is because the context object of the Activity is passed in when a custom WebView is built, so you need to remove WebView from the parent container first, and then destroy webview:

  rootLayout.removeView(webView);
  webView.destroy();

Determine whether WebView has scrolled to the bottom or top of the page:
The getScrollY()// method returns the distance from the top of the current visible area to the top of the entire page, that is, the distance from which the current content scrolls.
getHeight() or getBottom()// methods return the height of the current WebView container
getContentHeight() returns the height of the entire html, but it is not the same as the current height of the entire page. Because WebView has zooming function, the current height of the entire page should actually be the height of the original HTML multiplied by the zooming ratio. Therefore, the correct result should be:

    if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
        //Already at the bottom
    }

    if(webView.getScrollY() == 0){
        //At the top
    }

 

 

Some Ways to Avoid WebView Memory Leakage

1. You can start a new process for Activity of Webview and exit the current process directly at the end of the process.
Start a new process, the main code: AndroidManifest.xml configuration file code is as follows

    <activity
        android:name=".ui.activity.Html5Activity"
        android:process=":lyl.boon.process.web">
        <intent-filter>
            <action android:name="com.lyl.boon.ui.activity.htmlactivity"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>

Initiate Activity in the new process, which sends a Url:

    Intent intent = new Intent("com.lyl.boon.ui.activity.htmlactivity");
    Bundle bundle = new Bundle();
    bundle.putString("url", gankDataEntity.getUrl());
    intent.putExtra("bundle",bundle);
    startActivity(intent);

Then add System.exit(0) to onDestory() of Html5Activity to kill the current process.

2. Webview cannot be defined in xml, but created when needed, and Context uses getApplicationgContext(), as follows:

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mWebView = new WebView(getApplicationContext());
        mWebView.setLayoutParams(params);
        mLayout.addView(mWebView);

3. When Activity is destroyed, you can first let WebView load null content, then remove WebView, then destroy WebView, and finally empty it.
The code is as follows:

    @Override
    protected void onDestroy() {
        if (mWebView != null) {
            mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebView.clearHistory();

            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.destroy();
            mWebView = null;
        }
        super.onDestroy();
    }

 

 

Return key

Return to the page you visited last time

public boolean onKeyDown(int keyCode, KeyEvent event) {       
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {       
        mWebView.goBack();       
        return true;       
    }       
    return super.onKeyDown(keyCode, event);       
}

 

 

There is a very good Html5Activity loading class post out:

package com.lyl.web;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.lyl.test.R;

public class Html5Activity extends AppCompatActivity {

    private String mUrl;

    private LinearLayout mLayout;
    private WebView mWebView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);

        Bundle bundle = getIntent().getBundleExtra("bundle");
        mUrl = bundle.getString("url");

        Log.d("Url:", mUrl);

        mLayout = (LinearLayout) findViewById(R.id.web_layout);


        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mWebView = new WebView(getApplicationContext());
        mWebView.setLayoutParams(params);
        mLayout.addView(mWebView);

        WebSettings mWebSettings = mWebView.getSettings();
        mWebSettings.setSupportZoom(true);
        mWebSettings.setLoadWithOverviewMode(true);
        mWebSettings.setUseWideViewPort(true);
        mWebSettings.setDefaultTextEncodingName("utf-8");
        mWebSettings.setLoadsImagesAutomatically(true);

        //Call the JS method. Android version is larger than 17, with the annotation @JavascriptInterface
        mWebSettings.setJavaScriptEnabled(true);

        saveData(mWebSettings);

        newWin(mWebSettings);

        mWebView.setWebChromeClient(webChromeClient);
        mWebView.setWebViewClient(webViewClient);
        mWebView.loadUrl(mUrl);
    }

    /**
     * Multi-window problem
     */
    private void newWin(WebSettings mWebSettings) {
        //The _bank tag in html means that a new window is opened, sometimes it can't be opened, so we need to do the following
        //Then override the onCreateWindow method of WebChromeClient
        mWebSettings.setSupportMultipleWindows(true);
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    }


    /**
     * HTML5 data storage
     */
    private void saveData(WebSettings mWebSettings) {
        //Sometimes Web pages need to save some key data by themselves, and Android WebView needs to be set up by itself.
        mWebSettings.setDomStorageEnabled(true);
        mWebSettings.setDatabaseEnabled(true);
        mWebSettings.setAppCacheEnabled(true);
        String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
        mWebSettings.setAppCachePath(appCachePath);
    }

    WebViewClient webViewClient = new WebViewClient(){

        /**
         * When multiple pages are opened in the same WebView, they do not create new activity or call the system browser to open it.
         */
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

    };

    WebChromeClient webChromeClient = new WebChromeClient() {

        //========= HTML5 Location==========================================================
        //Privileges need to be added first
        //<uses-permission android:name="android.permission.INTERNET"/>
        //<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        //<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        @Override
        public void onReceivedIcon(WebView view, Bitmap icon) {
            super.onReceivedIcon(view, icon);
        }

        @Override
        public void onGeolocationPermissionsHidePrompt() {
            super.onGeolocationPermissionsHidePrompt();
        }

        @Override
        public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, false);//Note the function, the second parameter is whether to agree to the location permission, and the third is whether to want the kernel to remember.
            super.onGeolocationPermissionsShowPrompt(origin, callback);
        }
        //========= HTML5 Location==========================================================


        //========= Multi-window problem==========================================================
        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(mWebView);
            resultMsg.sendToTarget();
            return true;
        }
        //========= Multi-window problem==========================================================
    };


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }



Keywords: Android network Javascript html5

Added by Elusid on Sat, 29 Jun 2019 03:28:50 +0300