WebView is one of the most complex and powerful controls on Android. There are a lot of Settings that make you confused and sometimes you don’t know what to do with it. Add WebViewClient and WebChromeClient as internal classes, a bunch of business logic, make the Activity become messy, code readability is terrible, and finally forced to go to the road of encapsulation.

WebView encapsulates ideas

For the encapsulation of WebView, I believe that many people are abstracted in a base class and encapsulated into a BaseWebActivity or BaseWebFragment. For this encapsulation, it still cannot meet the needs of programmers like me who are obsessed with cleanliness, because the reusability is not high. And it’s easy to inflate the Activity or Fragment base class. Share my encapsulation ideas with you below.

First of all, let me show you the effect of my encapsulation



It’s packaged into a Web library called AgentWeb, and you’re welcome to use it.

You can see that there’s no WebSettings in there, and even WebChromeClient and WebViewClient don’t need to be configured, using neat chain calls.

The idea of AgentWeb encapsulation is to proxy a WebView from an Activity or Fragment. You don’t need to create and manage the WebView inside the Activity or Fragment. An Activity manages a WebView through AgentWeb, which is illustrated in a UML diagram.

BaseActivity encapsulates the UML diagram used





AgentWeb encapsulates the UML diagram used



BaseWebActivity combines webViews directly. Why is it not reusable? Mainly because WebView is attached to BaseWebActivity, it is not good for someone to inherit your Activity directly, because Java’s single inheritance relationship restricts the flexibility of using base classes. This is also the case in Effective Java where composition takes precedence over inheritance.

AgentWeb, on the other hand, is a stand-alone library that allows you to easily introduce in a single sentence, without relying on BaseWebActivity, as described above.

AgentWeb proxies webViews and subdivides them into classes to manage them. For example, WebCreator is responsible for creating webViews and the progress bar. WebSettings is responsible for setting up webviews. JsEntraceAccess is a unified entry point to Javascript method access, which makes each function independent of the other, and also makes AgentWeb a cleaner structure that adheres to the single responsibility principle. Too much source code will not be posted, the following to share some of the problems encountered in packaging WebView.

WebView encapsulation of some problems and solutions

There are a lot of problems with WebView packaging, such as common leaks, Js security, cross-source issues with low versions, context-induced onJsAlert failure, Android 4.4 file selection issues, etc.

Memory leaks

This problem is not easy to solve in earlier versions. Even if the following code is used to null sConfigCallback by reflection, some phones will still leak. For this problem, The only effective solution is to add the Android: Process =”: Web “attribute to the Web Activity in the AndroidManifest and then execute System.exit(0) in the Activity onDestroy; The following can solve part of the leakage

Remote code execution vulnerability caused by addJavascriptInterface API

This problem, which I’m sure you all know a little bit about, is caused by the injection class, from which you can find the Runtime object, through which you can execute shell commands. In order to solve the problem of compatibility with Android 4.2.2 and later versions, AgentWeb uses 360 Daniu’s solution to inject a javascript script into the Web page. Then, the script Prompt is used to communicate with Java, which solves the secure communication problem of addJavascriptInterface in 4.2.2. The rough implementation is given below

For example, the following injection class

For Android versions lower than 4.2.2, the injected objects are wrapped and spliced into the following script.

Injected script

The above script is injected via webView.loadURL (script).

Js executes the following method

The method body in the function above is executed, OnJsPrompt (WebView view, String URL, String message, String defaultValue, JsPromptResult result) message retrips the target method to be invoked, and then invokes the target method via reflection.

For the same origin cross – domain attack problem

What is the same origin policy? The same origin policy was developed by Netscape, and today’s major browsers follow this policy. Same origin means http://(protocol)www.google.com (host) :8080 (port) all three elements are the same, but it’s not that strict. IE, for example, ignores ports.

What does homology do? Same-origin data is securely accessible by default. For example the URL http://www.google.com: XXXX/login after logging in the browser will return to the cookies stored, browser for http://www.google.com:xxxx/index.html to this url will default to follow the former homologous, Then this URL can seamlessly access the cookies saved by Login.

It is well known that files and data between Android applications are not normally accessible to each other, but improper use of WebView, such as the following, can break this situation

If you set the Activity to exported=”true”, other applications can be started implicitly by using data as the URL to start the application, load scripts, traverse files or private files within the application, and upload them to the server.

This has been a problem with Android phones, and Google hasn’t fixed it, Just after the 4.2 version of the setAllowFileAccessFromFileURLs and mWebSettings setAllowUniversalAccessFromFileURLs set to false, Users didn’t intentionally turn it on, and higher than Android 4.2 is safe by default. AgentWeb uses the following Settings for this problem.

Context caused onJsAlert to fail

The problem root cause to prevent leak time to create new WebView (activity) getApplicationContext ()); Because you’re creating a WebView and you’re passing an Application, and the Application itself can’t pop a Dialog. So nothing! The solution to this problem is simply to pass in the Activity when you create a WebView, or implement the onJsAlert method yourself.

Android 4.4 File access

Android 4.4 WebView kernel officially has WebKit replaced with Chromium, which makes many APIS obsolete. This is a full stop for Google to officially announce the abandonment of WebKit. So it’s hard to make apps that are compatible with Android 4.4 or below WebView. 4.4 File access, you will find that 4.4 click on the input tag does not respond, suddenly ten thousand Ciomans in the crash, thank god there is Js communication, solution: You can access Java through Js, open the file selector, get the file, turn it into a Base64 string and pass it back to Js because the file path starts with Content:// and Js cannot parse it. (This code span is a bit large, will not paste the source code, interested can clone warehouse to see)

WebView is used after encapsulation

The App download: https://github.com/Justson/AgentWeb/blob/master/agentweb.apk

AgentWeb is used in fragments

Much simpler than the original WebFragment.

Js calls.

Not encapsulated

mWebView.loadUrl("javascript:callByAndroid("+"\"hello\""+","+"\" js\""+")");

After the encapsulation

mAgentWeb.getJsEntraceAccess().quickCallJs("callByAndroid","Hello","js");

github:https://github.com/Justson/AgentWeb