浏览器探究——UserAgent
首先看APP层对UA的使用情况
BrowserSettings对UA的维护
在BrowserSettings.java中定义了几个固定的UA值。
还包含了一个成员private WeakHashMap<WebSettings, String> mCustomUserAgents;该成员记录的是某个WebSettings被用户额外的设置的UA情况。浏览器中有唯一的一个BrowserSettings。但是每个WebView有一个对应的WebSettings。BrowserSettings的mCustomUserAgents用来记录所有的WebSettings的用户设置情况,这个所谓的用户设置情况在android 4.0上只是设置的桌面版UA的情况,即某个WebSettings被设置了桌面版UA,则该WebSettings的桌面版UA值被添加入该映射中。
同步WebSettings的UA
在BrowserSettings:: syncSetting中有对WebSettings的UA的同步情况。当mCustomUserAgents中存储的与该WebSettings对应的UA不为空时,则直接用mCustomUserAgents存储的值,即用户设置的桌面版的请求。否则通过SharedPreferences的配置情况来获取当前UA用的哪个值,也就是前面说的定义的几个固定值。当前android中并没有开放SharedPreferences中对UA的选择,提供的是debug情况下才可以选择。这部分如果有需求,其实可以自己修改来加入该功能的。即在SharedPreferences中可以提供对外的接口,让用户来选择默认使用哪种UA。然后在BrowserSettings::
syncSetting中可以把它作为一个默认UA值。
设置WebSettings的UA用的是WebSettings::setUserAgentString函数。
使用桌面UA的功能
Android 4.0提供了一个叫请求桌面版网站的功能,其实所谓的请求桌面版就是使用桌面版的UA。在BrowserSettings中有函数toggleDesktopUseragent(WebView view)就是用于在桌面版UA和非桌面版UA之前进行切换用的。
当使用桌面版UA时,会向mCustomUserAgents中设置于该WebSettings对应的桌面版UA值,并再通过WebSettings::setUserAgentString把做桌面版UA设置进去。可见mCustomUserAgents中存的只是个记录而已。
当再次执行toggleDesktopUseragent时,会移除mCustomUserAgents中与该WebSettings对应的桌面版UA值,并通过WebSettings::setUserAgentString把默认UA设置进去。
可见,判断一个WebSettings使用的是不是桌面版UA,就是通过查询mCustomUserAgents中与该WebSettings对应的值是否为NULL来判断的。
果然,在boolean BrowserSettings::hasDesktopUseragent(WebView view)中就是这么判断的。
获取UA值
由于每个WebView都有自己的UA,所以在app层获取UA时,不能通过BrowserSettings。而是要通过WebSettings来获取。通过WebView::getSettings()获取到与该WebView对应的WebSettings,然后再通过WebSettings::getUserAgentString()获取到对应的UA。UA主要用在http通讯上,由于app层也有一些用到http通讯的地方(比如获取某个URL的MimeType值,就是发http请求,然后查询http响应头信息的),所以需要通过这个过程来获取UA值。
总结APP层对UA的使用
APP层的WebSettings中有个mCustomUserAgents用来记录某个WebSettings使用桌面版UA的情况。
WebSettings中定义了几个固定的UA值,并提供了BrowserSettings::syncSetting的函数,可以在设置中扩展设置项来选择默认的UA值。
当前的默认UA值为null。
UA的真正设置是通过WebSettings::setUserAgentString接口设置的。
UA的获取是通过WebSettings::getUserAgentString接口获取的。
其次看FrameWork层对UA的维护情况
WebSettings中对UA的维护
由于每个UA关联一个WebView,所以每个WebSettings都维护与之对应的WebView使用的UA值。
WebSettings有两个与UA相关的成员
private String mUserAgent; //使用的UA值
private boolean mUseDefaultUserAgent; //使用的是否是默认的值,这里的默认值是指系统自己生成的UA值,即不是通过应用调用WebSettings:: setUserAgentString(参数为null值)设置的UA值。
UA的初始值
在WebSettings的构造函数中会设置mUseDefaultUserAgent为true,即使用的是默认UA值。mUserAgent的值是通过WebSettings:: getCurrentUserAgent接口获取到的。
WebSettings::getCurrentUserAgent
会通过android.os.Build获取到一些信息,通过framework/base/core/res/res/values/strings.xml获取一些固定值,再通过java.util.Local获取语言信息,等组合成一个UA值,作为返回值。
那么初始的UA值,就是这个组合出来的值。
WebSettings:: setUserAgentString
/**
* Set the WebView's user-agent string. If the string "ua" isnull or empty,
* it will use the system default user-agent string.
*/
该函数用于提供接口供外部设置UA值。
如果参数为null或者字符串长度为0,则使用getCurrentUserAgent接口来获取默认的UA,赋值给mUserAgent,并设置mUseDefaultUserAgent为true。
如果参数为一个有效的字符串,则用参数来设置mUserAgent。并设置mUseDefaultUserAgent为false。
当UA值有改变时,会执行WebSettings:: postSync通知同步。
WebSettings::getUserAgentString
/**
* Return the WebView's user-agent string.
*/
该函数用于提供接口供外部获取UA值。
这里先判断如果使用的是桌面版UA值,则直接返回mUserAgent的内容,如果mUseDefaultUserAgent为false,即曾经有人通过setUserAgentString主动设置过非空的UA值,则也直接返回mUserAgent的内容。
否则会先查询下java.util.Local是否有改变(与存在WebSettings的成员static Local sLocale做对比),如果有改变还是通过getCurrentUserAgent返回UA值。
这里就有个疑问,为什么不直接返回mUserAgent呢?默认情况下mUserAgent的值应该和getCurrentUserAgent返回的相等啊,其实不然,因为计算组合UA时有一条是要通过java.util.Local获取语言信息的,当前用户可能切换了语言,那么UA的值也就应该随之改变了。
最后在该函数中,如果通过java.util.Local改变了,那么还要执行WebSettings:: postSync通知同步。
WebSettings::postSync
该接口对自身的Handler发送了一个消息,在消息处理中,会调用nativeSync这个jni函数。用途是通知c层更新设置。
通过以上就完成了对UA的初始化,设置,查询了。
总结Framework层对UA的维护
总结下FrameWork层对UA的维护情况,其实就是WebSettings在构造时做了初始化的操作,并提供了一个设置一个获取的接口。
UA的默认值是通过WebSettings::getCurrentUserAgent获取的,这个接口是利用一些信息组织成一个UA值的。
C层对UA的使用
WebKit层有一个与java层WebSettings对应的在Source/WebKit/android/jni/WebSettings.cpp的c层的WebSettings
在这里c层直接可以访问java层的WebSettings的成员mUserAgent。
这里只有一个jni方法,就是与java层的nativeSync对应的函数WebSettings::Sync
WebSettings::Sync
该接口会把java层的WebSettings中各个成员的信息设置给WebCore::Settings这个类。
这样WebCore中的各个类就可以通过WebCore::Settings来获取到响应的设置信息了。
但是UA的信息却特例,它是设置给了android::WebFrame这个类了。
之后网络请求时使用UA就会通过android::WebFrame:: userAgentForURL来获取UA值了。
总结C层对UA的使用
通过与java层WebSettings对应的c层的jni下的WebSettings的sync这个jni接口,即时更新UA的值,并把UA值设置给android::WebFrame。
其他的c层类通过android::WebFrame:: userAgentForURL来获取UA值。
分享到:
相关推荐
如题,有比较清晰的汇总,在大家做摸拟登陆/手机开发/app开发的时候,可能会用到,可以给到大家选择。。希望对大家有用
可以访问手机端的浏览器,在手机上看视频,玩游戏屏幕太小,这个浏览器可以帮助大家解决屏幕小的问题
2021年9月最新浏览器useragent
浏览器UA切换 UserAgent UserAgentSwitcher.xml
Python UserAgent解析库——user_agents,判断如手机等访问设备 https://xercis.blog.csdn.net/article/details/108620963
C#代码获取WebBrowser中的 cookie和userAgent 参数,方法和请求类
最新浏览器useragent
里给大家推荐一款浏览器嗅探的jQuery插件useragent,兼容各大浏览器,在做项目的时候经常要用到,非常的实用
各种useragent,也是分析ua收集来的 涵盖各种手机机型的ua了,差不多1w多个
在分享页面上提供公司APP的下载...当然可以做得更完善一点,再加上判断是在移动设备打开还是在PC端浏览器打开的,更加细分一点,可以判断是在安卓系统的浏览器打开的还是IOS系统浏览器打开的。 if (browser.versions.m
检测浏览器,注意浏览器判断顺序,主要是基于userAgent做判断。 //检测浏览器 var client = function(){ var engine = { ie:0, gecko:0, webkit:0, khtml:0, opera:0, ver:null }; var browser = { //浏览器 ie: 0,...
python-user-agents:浏览器的user agent 解析器用于判断来源是电脑、手机、平板
Hive自定义函数的使用——useragent解析 从日志数据中分析一下操作系统、浏览器、版本使用情况,但是Hive中的函数不能直接解析useragent,于是可以写一个UDF来解析。useragent用于表示用户的当前操作系统,浏览器版本...
浏览器UA切换 UserAgent UserAgent,手机UA库,有10000多个,
Fake Useragent:各种各样的随机浏览器头 useragents
JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另 一种是通过分析浏览器的userAgent属性来判断的。本文对浏览器各自的userAgent特点做一分析,并给出判断方法: Windows操作系统...
(useragent:: isMobile ()) { //... } 检查当前设备是否为智能手机 if (useragent:: isSmartphone ()) { //... } 检查当前设备是否为平板电脑 if (useragent:: isTablet ()) { //... } 检查当前浏览器是否为Firefox ...
浏览器信息 浏览器: Chrome-谷歌浏览器 Chrome-谷歌浏览器开源版 IE-微软IE浏览器 Edge-微软新一代浏览器 火狐浏览器-火狐浏览器 Safari-苹果系统预设浏览器 歌剧-Opera浏览器 维瓦尔第-Opera联合创始人发布 ...
chrome也有这样的功能,但还是感觉易里面实现更简单,只要调用精易Web浏览器,设置下UA就可以,软件里设置了很多浏览器的UA,大家也可以自己添加,设置文件是UA_List.ini,格式是这样的:浏览器名称@@UserAgent@@...