有没有办法在没有活动WebView
的情况下检索浏览器的用户代理?
我知道可以通过WebView
获取它:
WebView view = (WebView) findViewById(R.id.someview);
String ua = view.getSettings().getUserAgentString() ;
但在我的情况下,我没有/需要一个webview对象,我不想仅仅为了检索用户代理字符串而创建它。
答案 0 :(得分:53)
如果你没有拥有,你可以尝试这样做
String ua=new WebView(this).getSettings().getUserAgentString();
编辑 -
getUserAgentString()
的文档说
返回WebView的用户代理字符串。
所以除非你申报一个,否则我认为你不能得到它。如果我错了,有人会纠正我
答案 1 :(得分:51)
如果你使用Android 2.1或更高版本,有一种更简单的方法。当然,这与Webview将返回的用户代理字符串不完全相同,但可能对您有用。
作为从Web视图中提取的另一个优势,您可以从任何线程(而不仅仅是UI线程)中使用它。
有一个名为http.agent的系统属性,可用于检索用户代理字符串。
String userAgent = System.getProperty("http.agent");
有关详细信息,请参阅Programmatically get User-Agent String。
答案 2 :(得分:35)
我曾经使用过DeRagan提出的solution。但事实证明,创建单个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);
}
}
它直接使用package-visible构造函数创建WebSettings
实例,如果由于某些原因(例如由于未来Android版本中的API更改)而无法使用 - 则默默地回退到“类似WebView”的解决方案。 / p>
<强>更新强>
正如@Skywalker5446指出的那样,从Android 4.2 / API 17开始,有一个公共静态方法来获取默认的用户代理值。我已经更新了我的代码,以便在支持的平台上使用该方法。
答案 3 :(得分:10)
从Android 2.1开始,你应该使用 System.getProperty(“http.agent”);
你也不需要先创建一个WebView,这就是优势, 你可以在非uithread中使用它。
问候史蒂夫
答案 4 :(得分:1)
感谢Idolon的回答,我的应用可以在后台处理。
但不知怎的,在运行2.3.3的AT&amp; 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)
答案 5 :(得分:1)
这是基于以前的答案的更新解决方案,当您为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();
}
}
}