Android技术点Android技术知识Android开发

Android Webview 线上动态设置 WebSettin

2018-01-29  本文已影响74人  Android技术分享

需求:

因项目需求调整,Webview需要支持多点伸缩等功能,而我们线上的APP只是做了JS、缓存等基础配置,那么,我们必须为Webview加上“多点伸缩”的配置,然后,重新发一个包。
想一想Android应用市场那么多,又要提交升级安装包,就头大了!!!
需要那面费劲吗?将来再扩展更多需求怎么办?

我们不是自己有服务器吗,如果Webview属性设计成可线上控制的不就行了。


分析:
1.查看WebSettings 源码,发现可设置的方法非常多,好在绝大多数方法都很简单,参数也几乎都是通用类型:String/booean/int等,如下:

setJavaScriptEnabled (boolean flag) ;
setJavaScriptCanOpenWindowsAutomatically (boolean flag) ;
setDefaultFixedFontSize (int size) ;
setDefaultFontSize (int size) 
setMinimumFontSize (int size) 
setEnableSmoothTransition (boolean enable) 
setSupportZoom (boolean support) 
setUserAgentString (String ua) 
......
......
......
supportMultipleWindows () 
supportZoom ()

2.那么我们,如果将显示设置做通用呢?
我们找出WebSetting方法的共同点,抽象出来,设计其配置格式(例如 method=?,params=? ,type =?,value=?等),需要什么属性,自行配上什么属性就可以了。
那么我们就可以做一张WebSetting的方法配置文件,放在服务器端,供客户端下载使用就行了。

{
          "method":"?",
          "params":[
              {
                  "type":"?",
                  "value":"?"
              }
          ]
   }

3.服务器端只需要拦截到客户端请求,返回压缩的配置文件即可(略)。
4.通过服务器端提供的URL,Android端获取到文件,解压缩,读取解析文件获得配置信息。
但是配置信息是JSON字符串(方法、参数等),我们如何让WebSetting执行呢?
其实,Java提供的反射机制可以帮我们解决这个问题。

经过分析,以上方案可行,下面就执行吧!!!


准备配置文件
我们做个简单点的,仅设置Js、Js打开窗体、webview伸缩的配置;

[
        {
            "method":"setJavaScriptCanOpenWindowsAutomatically",
            "params":[
                {
                    "type":"boolean",
                    "value":"true"
                }
            ]
        },
        {
            "method":"setJavaScriptEnabled",
            "params":[
                {
                    "type":"boolean",
                    "value":"true"
                }
            ]
        },
        {
            "method":"setBuiltInZoomControls",
            "params":[
                {
                    "type":"boolean",
                    "value":"true"
                }
            ]
        },
        {
            "method":"setDisplayZoomControls",
            "params":[
                {
                    "type":"boolean",
                    "value":"false"
                }
            ]
        }
]

服务器管理配置文件
我们这边交给了服务器端的人员去处理,所以略掉吧。
如果自己实现也很简单,需要注意的是,需要做文件压缩、验证等处理,要节省用户流量、确保配置数据安全!!!


Android端使用
1.下载到本地、解压缩、读取文件内容

2.定义实体类,用于封装WebSetting配置的方法、属性信息

     /**
     * webview属性设置类
     */
    class PropertySetting {
        String methodName;//方法名称
        Object[] args;//参数数组
        Class<?>[] argsClass;//参数类型数组
    }

3.解析JSON

/**
     * 解析属性设置数据
     * @param properties 属性配置字符串JSON格式
     * @return PropertySetting 集合
     */
    private List<PropertySetting> parseSettingData(String properties){
        if(properties==null || properties.length()==0){
            return null;
        }
        try {
            List<PropertySetting> propertyHolders = new ArrayList<>();
            JSONArray jsonArray = new JSONArray(properties);
            for(int i = 0; i <jsonArray.length() ; i++) {
                JSONObject jo = jsonArray.getJSONObject(i);
                if(jo == null || jo.isNull("method")){
                    continue;
                }
                PropertySetting propertyHolder = new PropertySetting();
                //获得方法名称
                propertyHolder.methodName = JsonUtil.getString(jo, "method");              
                //获得方法参数
                if(!jo.isNull("params")){
                    JSONArray jaParams = JsonUtil.getJSONArray(jo,"params");
                    if(jaParams.length() > 0){
                        Class<?>[] argsClass = new Class<?>[jaParams.length()];//参数类型数组
                        Object[] args = new Object[jaParams.length()];//参数数组
                        for(int j = 0;j<jaParams.length();j++){
                            String type = JsonUtil.getString(jaParams.getJSONObject(j),"type");
                            String value = JsonUtil.getString(jaParams.getJSONObject(j),"value");
                            parseTypeValue(j,type,value,argsClass,args);
                        }
                        propertyHolder.args = args;
                        propertyHolder.argsClass = argsClass;
                    }
                }
                //数据加到集合中
                propertyHolders.add(propertyHolder);
            }
            return propertyHolders;
        }catch (Exception ex){
            ExceptionProxy.catchException(ex);
        }
        return null;
    }

3.WebSetting设置方法属性

/**
     * 初始化WebSettings 属性
     * @param webSettings webview设置对象
     */
    public void initWebSettingsProperties(WebSettings webSettings){
        if(webSettings== null){
            return;
        }
        //属性集合
        List<PropertySetting> propertySettings = getPropertySetting();
        //通过反射设置属性
        for(PropertySetting propertyHolder : propertySettings){
            invokeMethod(webSettings, propertyHolder);
        }
    }
/**
     * 通过反射为webview设置属性
     * @param owner 对象
     * @param propertyHolder 属性
     */
    private void invokeMethod(Object owner, PropertySetting propertyHolder){
        try {
            //通过反射设置webview属性
            Class ownerClass = owner.getClass();
            Method method = ownerClass.getMethod(propertyHolder.methodName, propertyHolder.argsClass);
            method.invoke(owner, propertyHolder.args);
        }catch (Exception ex){
            ExceptionProxy.catchException(ex);
        }
    }

我们在初始化webview时,获得WebSetting,调用initWebSettingsProperties方法即可。

总结
WebSettings线上动态配置的功能要点回顾:
1.通过配置文件,实时、动态维护webview属性
(配置文件可改造成API,通过服务器端URL直接获取配置的JSON结构)
2.配置的文件生效(服务器端控制)
3.下载、解析获得JSON结构的配置文件
4.通过反射动态配置属性


该功能已应用在我们的APP中,我们Android端不用再担心新的属性配置或取消配置的需求了。
在实际项目中,我们的配置稍微复杂一些,考虑的东西多一些,例如:
1.不同域配置不同属性
2.不同android版本配置不同属性
3.等
因为怕影响大家理解,所以当前文档没有体现,我们只是将核心的知识点列了出来。
因为时间关系,没有写的太细,如果还有不明白的地方,欢迎留言。

上一篇下一篇

猜你喜欢

热点阅读