Подтвердить что ты не робот

Извлечение User-Agent программно

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

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

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

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

4b9b3361

Ответ 1

Если у вас есть, вы можете попробовать взять его вот так

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

Правка -

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

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

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

Ответ 2

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

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

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

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

Подробнее см. Программировать строку User-Agent.

Ответ 3

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

UPDATE

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

Ответ 4

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

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

приветствия steve

Ответ 5

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

Но каким-то образом на 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 в поле)

Ответ 6

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