Android 以编程方式检索用户代理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3626071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:03:13  来源:igfitidea点击:

Retrieve User-Agent programmatically

androidwebviewandroid-webviewuser-agent

提问by Laimoncijus

Is there a way to retrieve Browser's user-agent without having a WebViewin activity?

有没有办法在没有WebView活动的情况下检索浏览器的用户代理?

I know it is possible to get it via WebView:

我知道可以通过WebView以下方式获得它:

WebView view = (WebView) findViewById(R.id.someview);
String ua = view.getSettings().getUserAgentString() ;

But in my case I don't have/need a webview object and I don't want to create it just for retrieving user-agent string.

但在我的情况下,我没有/需要一个 webview 对象,我不想创建它只是为了检索用户代理字符串。

回答by Craig Russell

There is a much simpler way if you are on Android 2.1 or above. Granted this isn't the exact same User Agent string that a webview would return, but might serve you well enough for your purposes.

如果您使用的是 Android 2.1 或更高版本,则有一种更简单的方法。当然,这与 webview 将返回的用户代理字符串不完全相同,但可能足以满足您的目的。

As an additional advantage to pulling from web view, you can use this from any thread (not just the UI thread).

作为从 Web 视图拉取的额外优势,您可以从任何线程(不仅仅是 UI 线程)使用它。

There is a system property called http.agent, which can be used to retrieve the User-Agent string.

有一个名为 http.agent 的系统属性,可用于检索 User-Agent 字符串。

String userAgent = System.getProperty("http.agent");

See Programmatically get User-Agent Stringfor more details.

有关更多详细信息,请参阅以编程方式获取用户代理字符串

回答by DeRagan

If you don't haveone you can try taking it like this

如果你不一个你可以尝试把它像这样

String ua=new WebView(this).getSettings().getUserAgentString();

Edit-

编辑-

The doc for getUserAgentString()says

的文档getUserAgentString()

Return the WebView's user-agent string.

返回 WebView 的用户代理字符串

So i don't think you can get it unless you declare one. Some one correct me if i am wrong

所以我不认为你能得到它,除非你声明一个。如果我错了,有人纠正我

回答by Idolon

I used to use solutionproposed by DeRagan. But it turned out that creating a single WebViewinstance starts a thread "WebViewCoreThread" which stays on the background until application is terminated by the system. Maybe it doesn't consume too much resources but I don't like it anyway. So I use slightly different method now, which tries to avoid WebViewCoreThread creation:

我曾经使用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);
  }
}

It creates WebSettingsinstance directly using package-visible constructor and if that is not available for some reason (e.g. due to API changes in future Android versions) - silently falls back to "WebView-like" solution.

WebSettings直接使用包可见的构造函数创建实例,如果由于某种原因(例如,由于未来 Android 版本中的 API 更改)不可用 - 默默地回退到“类似 WebView”的解决方案。

UPDATE

更新

As pointed by @Skywalker5446, starting from Android 4.2/API 17, there is a public static method to get default user agent value. I've updated my code to use that method on the supported platforms.

正如@Skywalker5446所指出的,从Android 4.2/API 17 开始,有一个公共静态方法来获取默认用户代理值。我已更新我的代码以在支持的平台上使用该方法。

回答by HymansOnF1re

Since Android 2.1 you should use System.getProperty("http.agent");

从 Android 2.1 你应该使用System.getProperty("http.agent");

You also dont need to create a WebView first AND , thats the advantage, you can use it inside a non-uithread.

您也不需要先创建一个 WebView AND ,这就是优点,您可以在非 uithread 中使用它。

greetings steve

问候史蒂夫

回答by Monstieur

This is an updated solution based on previous answers that works when you compile for KitKat. Now the WebSettingsclass is abstract and the WebSettingsClassicclass has been removed.

这是基于以前的答案的更新解决方案,当您为 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();
        }
    }
}

回答by st_bk

Thanks to Idolon's answer my app could process this in the background.

感谢 Idolon 的回答,我的应用程序可以在后台处理这个。

But somehow on HTC Inspire 4G from AT&T that runs 2.3.3, it goes to the catch statement and it can be no longer run on the background thread. My solution for this is the following:

但不知何故,在运行 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;
    }
}

(suppose you have mContext and mUserAgent in the field)

(假设您在该字段中有 mContext 和 mUserAgent)