Получить User-Agent программно - PullRequest
34 голосов
/ 02 сентября 2010

Есть ли способ получить пользовательский агент браузера без активности WebView?

Я знаю, что можно получить через WebView:

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

Но в моем случае у меня нет / нужен объект webview, и я не хочу создавать его только для получения строки user-agent.

Ответы [ 6 ]

54 голосов
/ 02 сентября 2010

Если у вас нет , у вас есть один, вы можете попробовать взять его следующим образом:

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

Edit-

Документ для getUserAgentString() говорит

Возвращает строку пользовательского агента WebView .

Так что я не думаю, что вы можете получить его, если не объявите об этом.Кто-нибудь поправит меня, если я ошибаюсь

51 голосов
/ 07 сентября 2012

Существует гораздо более простой способ, если вы используете Android 2.1 или выше. Конечно, это не та же строка User Agent, которую вернул бы веб-просмотр, но она может послужить вам достаточно для ваших целей.

В качестве дополнительного преимущества при извлечении из веб-представления вы можете использовать его из любого потока (не только потока пользовательского интерфейса).

Существует системное свойство http.agent, которое можно использовать для получения строки User-Agent.

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

См. Программно получить строку User-Agent для более подробной информации.

35 голосов
/ 10 марта 2011

Я использовал решение , предложенное ДеРаганом.Но оказалось, что создание одного экземпляра 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 напрямую, используя конструктор, видимый в пакете, и если он недоступен по какой-либо причине (например, из-за APIизменения в будущих версиях Android) - молча возвращается к решению, подобному WebView.

ОБНОВЛЕНИЕ

Как указано @ Skywalker5446 , начинаяиз Android 4.2 / API 17 существует общедоступный статический метод для получения значения пользовательского агента по умолчанию.Я обновил свой код для использования этого метода на поддерживаемых платформах.

10 голосов
/ 05 ноября 2013

Начиная с Android 2.1, вы должны использовать System.getProperty ("http.agent");

Вам также не нужно сначала создавать WebView И это преимущество, которое вы можете использоватьэто внутри непрочитанного.

привет Стив

1 голос
/ 02 июня 2014

Это обновленное решение, основанное на предыдущих ответах, которое работает при компиляции для 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();
        }
    }
}
1 голос
/ 03 сентября 2011

Благодаря ответу Идолона мое приложение может обработать это в фоновом режиме.

Но почему-то в HTC Inspire 4G от AT & T, который работает под 2.3.3, он переходит к оператору 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 в поле)

...