Google's first batch of Android developers in the world: teach you the correct posture of Webview in the 5G era

Preface

As Android developers, we all know that a high-performance webkit kernel browser is built into the mobile phone, which is packaged as a component called WebView in the SDK. Today I will talk about the detailed usage of WebView in Android

Original address: https://kymjs.com/code/2015/05/03/01

As Android developers, we all know that a high-performance webkit kernel browser is built into the mobile phone, which is packaged as a component called WebView in the SDK.
In the development process, you should pay attention to several points:
1. This is the most basic AndroidManifest.xml must be added to access network permissions.
2. If there is Javascript in the visited page, the WebView must be set to support Javascript.

WebView.getSettings().setJavaScriptEnabled(true);

3.If there is a link in the page, if you want to click on the link to continue to respond in the current browser, instead of responding to the link in the newly opened Android system browser, you must override the WebViewClient object of WebView.

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

4. If you do not do any processing, browse the web page, click the system "Back" button, the entire Browser will call finish() and end itself, if you want to browse the web page back instead of launching the browser, you need to process and consume in the current Activity Disable the Back event. (The code is somewhat simplified)

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

Intermodulation with js

Since web pages can be displayed, of course, you can also let web pages operate local methods. (Because one line can't be written, I adjusted the indentation)

public class WebViewDemo extends Activity { 
    private WebView mWebView;
    private Handler mHandler = new Handler(); 

    public void onCreate(Bundle icicle) { 

    setContentView(R.layout.WebViewdemo);
    mWebView = (WebView) findViewById(R.id.WebView); 
    WebSettings webSettings = mWebView.getSettings(); 
    webSettings.setJavaScriptEnabled(true); 
    mWebView.addJavascriptInterface(new Object() {
      public void clickOnAndroid() {
          mHandler.post(new Runnable() {
              public void run() { 
                  mWebView.loadUrl("javascript:wave()");
              }
          });
      }
    }, "demo"); 
    mWebView.loadUrl("file:///android_asset/demo.html"); 

    }
}

Let’s look at the method addJavascriptInterface(Object obj, String interfaceName). This method binds a java object to a javascript object. The javascript object name is interfaceName(demo), and the scope is Global. In this way, after initializing the WebView, it is loaded in the WebView You can directly access the bound java object through javascript:window.demo in the page. Let's see how it is called in html.

<html>
<script language="javascript">
  function wave() {
    document.getElementById("droid").src="android_waving.png";
  }
</script>
<body>
  <a onClick="window.demo.clickOnAndroid()">
  <img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br> Click me! </a>
</body>
</html>

In this way, the clickOnAndroid() method of the java object can be called in javascript, and we can also define many methods in this object (such as sending text messages, calling the phone system functions such as the contact list), here the wave() method is called in java javascript example.

One point needs to be explained: the Java objects and methods to be bound in the addJavascriptInterface method must run in another thread, and cannot run in the thread that constructed it.This is also the purpose of using Handler.

In-depth use of WebView

Let js call Android code

  1. First, briefly describe the difference between WebView, WebViewClient, and WebChromeClient:
    In the design of WebView, not everything has to be done by the WebView class, and some chores are assigned to other people, so that WebView can concentrate on its own analysis and rendering work. WebViewClient is to help WebView handle various notifications, request events, etc., WebChromeClient is to assist WebView in processing Javascript dialogs, website icons, and website titles.

  2. Function implementation:
    Use the WebView in android to load an html web page, define a button in the html web page, and click the button to pop up a toast.

  3. Implementation steps:
    First define an interface class, pass the context object in, and define the method to be implemented in js in the interface class.
    Then define an html file under the assets resource package, define a button in the file. The click event of the button is defined as a js function. 
    Then define a WebView component in xml, get the WebView in the activity class, and set the WebView parameters, Pay special attention here to set up WebView to support js and add the defined js interface class to WebView, and then you can use the function defined in the interface class in js. Namely:

    myWebView.getSettings().setJavaScriptEnabled(true);

    myWebView.addJavascriptInterface(new JavaScriptinterface(this),“android”);

Finally, the method to load local html files using WebView is:

myWebView.loadData(htmlText,"text/html", "utf-8");

The htmltext here is to read the content of the assets reported in the html as a string.
4. Realize the use of the return key to return to the previous page:
set the WebView button monitoring, monitor the expired return key and determine whether the web page can be returned, Use WebView's goBack() to return to the previous page.

WebView cache

If the WebView control is used in the project, when the html page is loaded, two folders, database and cache, will be generated in the /data/data/package name directory (my phone is not rooted, so I won’t take a screenshot).
The requested URL record is saved in WebViewCache.db, and the content of the URL is saved in the WebViewCache folder. You can try it yourself, define an html file, display a picture in it, load it with WebView, and try again Read this picture from the cache and display it.

WebView delete cache

In fact, you already know the location of the cache, so deleting it is very simple. Get the cache and delete it.
//Delete the cache saved on the phone

private int clearCacheFolder(File dir,long numDays) { 
  int deletedFiles = 0;
  if (dir!= null && dir.isDirectory()){
    try {
      for (File child:dir.listFiles()){
          if (child.isDirectory()) {
            deletedFiles += clearCacheFolder(child, numDays);
        }
        if (child.lastModified() < numDays) {
          if (child.delete()) {
           deletedFiles++; 
          }
        }
      }
    } catch(Exception e) {
      e.printStackTrace(); 
    }
  }
  return deletedFiles; 
}

Whether to enable the cache function is also controllable ruby //优先使用缓存: WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //不使用缓存: WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

Add the following code when exiting the application to completely clear the cache java File file = CacheManager.getCacheFileBaseDir(); if (file != null && file.exists() && file.isDirectory()) { for (File item : file.listFiles()) { item.delete(); } file.delete(); } context.deleteDatabase("WebView.db"); context.deleteDatabase("WebViewCache.db");

WebView handles 404 errors

There is still a problem when displaying the webpage, that is, the webpage may not be found, and of course WebView can also handle it (the code is too much if all the code is posted, and only the important part is posted here) java public class WebView_404 extends Activity { private Handler handler = new Handler() { public void handleMessage(Message msg) { if(msg.what==404) {//主页不存在 //载入本地 assets 文件夹下面的错误提示页面 404.html web.loadUrl("file:///android_asset/404.html"); }else{ web.loadUrl(HOMEPAGE); } } }; @Override protected void onCreate(Bundle savedInstanceState) { web.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrl(WebView view,String url) { if(url.startsWith("http://") && getRespStatus(url)==404) { view.stopLoading(); //载入本地 assets 文件夹下面的错误提示页面 404.html view.loadUrl("file:///android_asset/404.html"); }else{ view.loadUrl(url); } return true; } }); new Thread(new Runnable() { public void run() { Message msg = new Message(); //此处判断主页是否存在,因为主页是通过 loadUrl 加载的, //此时不会执行 shouldOverrideUrlLoading 进行页面是否存在的判断 //进入主页后,点主页里面的链接,链接到其他页面就一定会执行 shouldOverrideUrlLoading 方法了 if(getRespStatus(HOMEPAGE)==404) { msg.what = 404; } handler.sendMessage(msg); }).start(); } }

Determine whether the WebView has scrolled to the bottom of the page

There is a getScrollY() method in View, which can return the distance from the top of the current visible area to the top of the entire page, which is the distance of the current content scrolling.
There are also getHeight() or getBottom() methods that return the height of the current View container.
In ViewView, there is also a getContentHeight() method that can return the height of the entire html page, but it is not equivalent to the height of the current entire page, because WebView has zoom Features. You can enable or disable the zoom function of webview with the following code.

mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);

So the current height of the entire page should actually be the height of the original html multiplied by the zoom ratio. Therefore, the corrected result, the accurate judgment method should be:

 // 如果已经处于底端
if(WebView.getContentHeight*WebView.getScale() -(webvi ew.getHeight()+WebView.getScrollY())){ 
  //XXX
}

WebView gets the session problem in the server

Next, we will talk about the following two questions:
1. How does the WebView in Android obtain the value of jsessionid of the server page
? 2. How does the WebView of Android set the obtained jsessionid value to the server, so that they are in the same jsessionid. In the reply,
it's actually very, very simple, just a few methods:

CookieManager cm = CookieManager.getInstance(); 
cm.removeAllCookie();
cm.getCookie(url);
cm.setCookie(url, cookie);

There is also a CookieSyncManager, maybe you will see it in some old projects. To understand from the name, it should actually be an asynchronous buffer. However, we see that this method has been marked as obsolete. Looking at the source code, you can see that the reason for the obsolescence is that WebView is now automatically cached asynchronously, so this class has no meaning. 

WebView clears local cookies

First of all, it must be cleared and added. Here is a tool for everyone:

    /***
     * 如果用户已经登录,则同步本地的cookie到webview中
     */
    public void synCookies() {
        if (!CacheUtils.isLogin(this)) return;
        CookieSyncManager.createInstance(this);
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeSessionCookie();//移除
        String cookies = PreferenceHelper.readString(this, AppConfig.COOKIE_KEY, AppConfig.COOKIE_KEY);
        KJLoger.debug(cookies);
        cookieManager.setCookie(url, cookies);
        CookieSyncManager.getInstance().sync();
    }

When using the web version of Taobao or Baidu to log in, WebView will automatically log in to the last account! (Because WebView records cookies for account and password) Therefore, it is necessary to clear SessionCookie.
Then CookieManager also provides us with a method to clear cookies 
CookieManager.getInstance().removeSessionCookie();

By the way, WebView itself also records the html cache. In the previous blog, I talked about a way to clean up the cache through file operations. Later I found out that the webview itself provides a way to clean up the cache. The parameters are True refers to whether the disk files are included or not. The effect of passing true is the same as what we said yesterday:

webview.clearCache(true);
webview.clearHistory();

Tell a case

After talking about so much theoretical knowledge, I will finally talk about a use case. WebView can be divided into two methods in actual use. The first method is similar to QQ WeChat. Use loadUrl to display a link directly. This method is too simple. Just pass a url, so I won’t say more. .
Then we need to talk about the second one in detail. For similar implementations, you can look at the open source Chinese client, Netease News client, Love Blog, and other client implementations. They are actually a web page displayed through webview. But it's not just loadurl, but it loads an already obtained html source code in the form of a string. The advantage of this is that the displayed page can be completely defined according to your own preferences. For example, if I want to add an image at the end, it is as simple as inserting an img tag at the end of the html string. As for the method of use, we have actually mentioned it above:

myWebView.loadData(htmlText,“text/html”, “utf-8”);

The htmltext is the html string we need to load, and this method can be used to directly display this string as a web page.
Finally, summarize the applicable scenarios of the two methods. The first method of loading links is suitable for an interface (Activity or Fragment) when there is only one WebView or WebView occupies a large part, and the content we want to display is unknown, then Naturally, it is more appropriate to use the loadurl method. For example, when QQ chats, the other party sends a link, and when QQ parses that the text is a URL, it loads it through webview. The latter is suitable for customized content, which is generally used when you can specify the content of the system webpage and the content to be displayed. As for the advantage, as mentioned above, the customization is much better.

End of sentence

On the paper, it’s still shallow, and the wall is cracked. It is recommended that friends who have more time to go to station B to watch the video explanation: Google’s first batch of Android developers in the world: teach you the correct posture of Webview in the 5G era.

Welcome to follow my short book, share Android dry goods, and exchange Android technology.
If you have any insights on the article, or any technical questions, you can leave a message in the comment area to discuss, and I will answer you religiously.
Everyone is also welcome to come to my station B to play with me. There are videos explaining the difficulties of advanced technology of various Android architects.
Station B is through train: https://space.bilibili.com/484587989

Guess you like

Origin blog.csdn.net/Androiddddd/article/details/109746810