Plugin management mechanism for Android and WebView

Source: Internet
Author: User

Plugin management mechanism for Android and WebView

As mentioned in the previous article, when WebViewClient or WebChromeClient is used to handle requests sent from the html page for reasons, the corresponding service name will be used, the operation method and corresponding parameter data are passed to a class called PluginManager.

What is the role of the PluginManager class?

As you know, when using features in the Android native environment, such as the photo camera, such as photo album, these features are scattered and you cannot tell when these features are required, these functions are not required at any time, so we hope to be able to load them when necessary like a plug-in, and ignore them when not needed, while the PluginManager class is such a management class.

It is mainly responsible for several things:

1) when entering the HTML page, load the control we have defined.

mPluginManager = new PluginManager(this);mPluginManager.loadPlugin();

So how does PluginManager know how many plugins will be loaded in this application to respond to requests from Html pages?

We define it through a configuration file named plugin. xml.

     
      
      
         
  
 


For example, in the above configuration file, we will load the App, Toast, Dialog and User plug-ins.

It can be said that Toast and Dialog are both display windows in the Android native environment. Although we use html pages to implement the interface, in order to maintain the consistency of the entire application, we will use the Toast or custom dialog box controls in the native environment.

Define what is needed here.

Let's take a look at the loadPlugin method:

public void loadPlugin() {int identifier = context.getResources().getIdentifier("plugins", "xml",context.getPackageName());if (identifier == 0) {pluginConfigurationMissing();}XmlResourceParser xml = context.getResources().getXml(identifier);try {int eventType = -1;while ((eventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {if (eventType == XmlResourceParser.START_TAG) {String name = xml.getName();if ("plugin".equals(name)) {String pluginName = xml.getAttributeValue(null, "name");String className = xml.getAttributeValue(null, "class");configs.put(pluginName, className);}}}} catch (XmlPullParserException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

As you can see, this is to parse the plugins. xml file, and then put the corresponding plug-in class name into configs. configs is defined as follows:

private HashMap
 
   configs = new HashMap
  
   ();private HashMap
   
     plugins = new HashMap
    
     ();
    
   
  
 

Through the loadPlugin method, we will be in plugins. the plug-in defined in xml is loaded into configs. In configs, only the class name is stored, while in plugins, the implementation is implemented. However, we do not need to care about this here.

Here, the name attribute defined in the plugins. xml file is the service name.

2) Find the corresponding Plugin for the request based on the service name and operation method of the request.

String execResult = mPluginManager.exec("service", "action", args);

Let's take a look at the exec method,

public String exec(String service, String action, JSONObject args) throws PluginNotFoundException {        IPlugin plugin = getPlugin(service);...PluginResult result = plugin.exec(action, args);...}

As shown in the preceding logic, PluginManager uses the getPlugin method to obtain the corresponding service, as shown below:

public IPlugin getPlugin(String pluginName) throws PluginNotFoundException {String className = configs.get(pluginName);if(className==null){throw new PluginNotFoundException(pluginName);}if (plugins.containsKey(className)) {return plugins.get(className);} else {return addPlugin(className);}}


In this way, we get a Plugin implementation class that implements the IPlugin interface.

IPlugin is an interface defined as follows:

Public interface IPlugin {public static final String SERVICE = "service"; public static final String ACTION = "action"; public static final String ARGS = "args "; /*** execute the request ** @ param action * function * @ param args * parameter * @ return pluginResult result */public PluginResult exec (String action, JSONObject args) throws ActionNotFoundException;

The most important method defined in it is the exec method. Every custom plug-in must implement this interface. However, here we first implement an abstract base class Plugin, it implements some public logic, and the specific implementation is inherited by the subclass of Plugin.

public abstract class Plugin implements IPlugin {protected DroidHtml5 context;

For example, if we take the Toast class above, it will inherit Plugin, and then implement the corresponding logic based on the corresponding service, and call the Toast of the native environment.

public class Toast extends Plugin {@Overridepublic PluginResult exec(String action, JSONObject args)throws ActionNotFoundException {if ("makeTextShort".equals(action)) {return makeTextShort(args);}else if ("makeTextLong".equals(action)) {return makeTextLong(args);} else {throw new ActionNotFoundException("Toast", action);}}private PluginResult makeTextShort(JSONObject args) {try {String text = args.getString("text");android.widget.Toast.makeText(context, text, android.widget.Toast.LENGTH_SHORT).show();} catch (JSONException e) {e.printStackTrace();return PluginResult.newErrorPluginResult(e.getMessage());}return PluginResult.newEmptyPluginResult();}private PluginResult makeTextLong(JSONObject args) {try {String text = args.getString("text");android.widget.Toast.makeText(context, text, android.widget.Toast.LENGTH_LONG).show();} catch (JSONException e) {e.printStackTrace();return PluginResult.newErrorPluginResult(e.getMessage());}return PluginResult.newEmptyPluginResult();}}


From the above code, I believe that everyone can easily understand the plug-in mechanism.

3) call it from the Html page.

We have defined such a plug-in mechanism in the Android native environment. In Html, we can also have such an interface method to correspond to different plug-ins, so we also define various objects in javascript.

For example, in the Toast plug-in described above, we can define a corresponding object in javascript, as follows:

var Toast = {makeTextShort : function(text) {return exec("Toast", "makeTextShort", JSON.stringify(text));},makeTextLong : function(text) {return exec("Toast", "makeTextLong", JSON.stringify(text));}}

Here, we can see that the makeTextShort method of Toast will call the exec method mentioned in the previous article, because the pop-up window shows that this kind of thing must be synchronized and it won't be said that the process will be completed for a while, suddenly, I ran out of a box and told me that you did something wrong, right.

Here, the service name (Toast), the Operation Method (makeTextShort), and the displayed content (JSON. stringfy (text) and so on through the exec method, and then use the onJsPrompt method of WebChromeClient to pass the command to PluginManager, which is processed by PluginManager.

public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result) {System.out.println("onJsPrompt:defaultValue:" + defaultValue + "|" + url + "," + message);JSONObject args = null;JSONObject head = null;try {// message:{"service" : "XX", "action" : "xx"}head = new JSONObject(message);if (defaultValue != null && !defaultValue.equals("")) {try {args = new JSONObject(defaultValue);} catch (Exception e) {e.printStackTrace();}}String execResult = mPluginManager.exec(head.getString(IPlugin.SERVICE),head.getString(IPlugin.ACTION), args);result.confirm(execResult);return true;

4) We will write these defined plug-in objects, as well as synchronous (exec) and asynchronous (exec_sync) methods into a javascript file for convenient unified management, therefore, the content of this file is generally as follows:

Var Toast = {makeTextShort: function (text) {return exec ("Toast", "makeTextShort", JSON. stringify (text);}, makeTextLong: function (text) {return exec ("Toast", "makeTextLong", JSON. stringify (text);} var Dialog = {...} var AndroidHtml5 = {.... /** exec_asyn call method @ params {JSONObject} cmd service name and Action Command @ params {String} args parameter */callNative: function (cmd, args, success, fail) {....},... callBackJs: function (result, key ){...}}; /** synchronous interaction interface between Html5 and Android */var exec = function (service, action, args) {var json = {"service": service, "action": action }; var result_str = prompt (JSON. stringify (json), args); var result; try {result = JSON. parse (result_str);} catch (e) {console. error (e. message );}...} /** Asynchronous interaction interface between Html5 and Android */var exec_asyn = function (service, action, args, success, fail) {var json = {"service": service, "action": action}; var result = AndroidHtml5.callNative (json, args, success, fail );}

End.





Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.