Android Webview 线上动态设置 WebSettin
需求:
因项目需求调整,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.等
因为怕影响大家理解,所以当前文档没有体现,我们只是将核心的知识点列了出来。
因为时间关系,没有写的太细,如果还有不明白的地方,欢迎留言。