2010-09-02 3 views
28

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

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

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

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

ответ

41

Если вы не имеют один вы можете попробовать принимать его как этот

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

Edit-

Док для getUserAgentString() говорит

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

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

+1

Спасибо, это работает. Было бы неплохо обойти это без создания объекта, но кажется, что это действительно невозможно ... – Laimoncijus

32

Раньше я использовал solution, предложенный 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-like».

UPDATE

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

+1

Этот метод не удался на Android 4.2, 'WebSettings' теперь является абстрактным, хотя существует' WebSettingsClassic', вызывающий частные API всегда не изящный способ, он просто провалится в будущем, и вы не сможете исправить его без обновления. – neevek

+1

В Android 4.2/API 17 существует общедоступный статический метод для получения этого значения: WebSettings.getDefaultUserAgent (Context), поэтому вы можете добавить проверку на этот уровень API и на этот трюк. –

+0

@ Skywalker5446 Спасибо за полезную информацию, я обновлю свой ответ соответственно. – Idolon

1

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

Но как-то на 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 в области)

+0

Вероятно, вы хотите либо «quit()« Looper », либо« join »() использовать поток или использовать' wait() 'и' notify() '/' notifyAll() ', так что mUserAgent гарантированно будет изменен. В настоящее время метод может вернуться до обновления дочернего потока mUserAgent. – yingted

+0

Hi. Я изменил ту часть, которую вы указали. –

41

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

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

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

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

Для получения более подробной информации см. Programmatically get User-Agent String.

+6

Это не пользовательский агент браузера, о чем просили. Тем не менее, это хорошо работает для многих целей. – lilbyrdie

+0

Это строка ** User-Agent **, которую WebView будет использовать для самосознания ** на хосте ** текущей загруженной страницы в WebView. На всякий случай вам нужно подключиться через HTTP Transport к любому удаленному хосту, чем это самый элегантный способ идентифицировать себя как Android WebView. –

10

С Android 2.1 вы должны использовать System.getProperty («http.agent»);

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

поздравление стив

+3

Это не ответ на вопрос. Это дает пользователю ganet устройства, а не веб-просмотр. – trante

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(); 
     } 
    } 
}