有没有办法在没有WebView
活动的情况下检索浏览器的用户代理?
我知道可以通过以下方式获得它WebView
:
WebView view = (WebView) findViewById(R.id.someview);
String ua = view.getSettings().getUserAgentString() ;
但在我的情况下,我没有/不需要 webview 对象,我不想仅仅为了检索用户代理字符串而创建它。
有没有办法在没有WebView
活动的情况下检索浏览器的用户代理?
我知道可以通过以下方式获得它WebView
:
WebView view = (WebView) findViewById(R.id.someview);
String ua = view.getSettings().getUserAgentString() ;
但在我的情况下,我没有/不需要 webview 对象,我不想仅仅为了检索用户代理字符串而创建它。
如果你没有,你可以试试这样
String ua=new WebView(this).getSettings().getUserAgentString();
编辑-
文档getUserAgentString()
说
返回 WebView 的用户代理字符串。
因此,除非您声明一个,否则我认为您无法获得它。如果我错了,有人纠正我
如果您使用的是 Android 2.1 或更高版本,则有一种更简单的方法。当然,这与 webview 将返回的用户代理字符串并不完全相同,但可能会为您提供足够好的服务来满足您的目的。
作为从 Web 视图中提取的另一个优势,您可以从任何线程(不仅仅是 UI 线程)使用它。
有一个名为 http.agent 的系统属性,可用于检索 User-Agent 字符串。
String userAgent = System.getProperty("http.agent");
有关详细信息,请参阅以编程方式获取用户代理字符串。
我曾经使用DeRagan 提出的解决方案。但事实证明,创建单个WebView
实例会启动一个线程“WebViewCoreThread”,该线程会一直停留在后台,直到应用程序被系统终止。也许它不会消耗太多资源,但我还是不喜欢它。所以我现在使用稍微不同的方法,它试图避免创建 WebViewCoreThread:
// You may uncomment next line if using Android Annotations library, otherwise just be sure to run it in on the UI thread
// @UiThread
public static String getDefaultUserAgentString(Context context) {
if (Build.VERSION.SDK_INT >= 17) {
return NewApiWrapper.getDefaultUserAgent(context);
}
try {
Constructor<WebSettings> constructor = WebSettings.class.getDeclaredConstructor(Context.class, WebView.class);
constructor.setAccessible(true);
try {
WebSettings settings = constructor.newInstance(context, null);
return settings.getUserAgentString();
} finally {
constructor.setAccessible(false);
}
} catch (Exception e) {
return new WebView(context).getSettings().getUserAgentString();
}
}
@TargetApi(17)
static class NewApiWrapper {
static String getDefaultUserAgent(Context context) {
return WebSettings.getDefaultUserAgent(context);
}
}
它直接使用包可见的构造函数创建WebSettings
实例,如果由于某种原因(例如由于未来 Android 版本中的 API 更改)不可用 - 默默地回退到“类似 WebView”的解决方案。
更新
正如@Skywalker5446所指出的,从 Android 4.2/API 17 开始,有一个公共静态方法可以获取默认的用户代理值。我已更新我的代码以在受支持的平台上使用该方法。
从 Android 2.1 开始,您应该使用System.getProperty("http.agent");
您也不需要先创建 WebView AND,这就是优势,您可以在非 uithread 中使用它。
问候史蒂夫
这是基于先前答案的更新解决方案,当您为 KitKat 编译时有效。现在WebSettings
该类是抽象的,并且WebSettingsClassic
该类已被删除。
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static String getUserAgent(final Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return WebSettings.getDefaultUserAgent(context);
}
else {
try {
final Class<?> webSettingsClassicClass = Class.forName("android.webkit.WebSettingsClassic");
final Constructor<?> constructor = webSettingsClassicClass.getDeclaredConstructor(Context.class, Class.forName("android.webkit.WebViewClassic"));
constructor.setAccessible(true);
final Method method = webSettingsClassicClass.getMethod("getUserAgentString");
return (String) method.invoke(constructor.newInstance(context, null));
}
catch (final Exception e) {
return new WebView(context).getSettings()
.getUserAgentString();
}
}
}
感谢 Idolon 的回答,我的应用程序可以在后台处理这个问题。
但不知何故,在运行 2.3.3 的 AT&T 的 HTC Inspire 4G 上,它进入了 catch 语句,它不能再在后台线程上运行。我的解决方案如下:
public static String getUserAgent(Context context) {
try {
Constructor<WebSettings> constructor = WebSettings.class.getDeclaredConstructor(Context.class, WebView.class);
constructor.setAccessible(true);
try {
WebSettings settings = constructor.newInstance(context, null);
return settings.getUserAgentString();
} finally {
constructor.setAccessible(false);
}
} catch (Exception e) {
String ua;
if(Thread.currentThread().getName().equalsIgnoreCase("main")){
WebView m_webview = new WebView(context);
ua = m_webview.getSettings().getUserAgentString();
}else{
mContext = context;
((Activity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
WebView webview = new WebView(mContext);
mUserAgent = webview.getSettings().getUserAgentString();
}
});
return mUserAgent;
}
return ua;
}
}
(假设您在该字段中有 mContext 和 mUserAgent)