2010-09-02 8 views
28

¿Hay alguna manera de recuperar el user-agent del navegador sin tener un WebView en actividad?Recuperar User-Agent programmatically

Yo sé que es posible conseguirlo a través de WebView:

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

Pero en mi caso no tengo/necesitará un objeto en vista web y no me desee crear sólo para recuperar el usuario cadena de agente.

Respuesta

41

Si no tienen uno puede intentar tomarlo como esto

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

Editar-

El doc para getUserAgentString() dice

Volver cadena de agente de usuario del WebView.

Así que no creo que pueda obtenerlo a menos que lo declare. Alguien me corrige si estoy equivocado

+1

Gracias, funciona. Sería bueno sortearlo sin crear un objeto, pero parece que no es realmente posible ... – Laimoncijus

32

Solía ​​usar solution propuesto por DeRagan. Pero resultó que la creación de una única instancia de WebView inicia un hilo "WebViewCoreThread" que permanece en el fondo hasta que el sistema finaliza la aplicación. Tal vez no consume demasiados recursos pero no me gusta de todos modos. Así que utilizo método ligeramente diferente ahora, que trata de evitar la creación 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); 
    } 
} 

Se crea WebSettings instancia directamente utilizando el constructor paquete visible y si eso no está disponible por alguna razón (por ejemplo, debido a cambios en la API en el futuro Android versiones): regresa silenciosamente a la solución "similar a WebView".

ACTUALIZACIÓN

Como se señaló por @Skywalker5446, a partir de Android 4.2/API 17, hay un método estático público para obtener el valor de agente de usuario por defecto. He actualizado mi código para usar ese método en las plataformas compatibles.

+1

Este método fallará en Android 4.2, 'WebSettings' ahora es abstracto, aunque hay un' WebSettingsClassic', llamar a las API privadas es siempre no de una manera elegante, fallará en el futuro y no podrá solucionarlo sin una actualización. – neevek

+1

En Android 4.2/API 17, hay un método público estático para obtener este valor: WebSettings.getDefaultUserAgent (Context), por lo que podría agregar un control para ese nivel de API también a este truco. –

+0

@ Skywalker5446 Gracias por la información útil, actualizaré mi respuesta en consecuencia. – Idolon

1

Gracias a la respuesta de Idolon, mi aplicación podría procesar esto en segundo plano.

Pero de alguna manera en HTC Inspire 4G de AT & T que ejecuta 2.3.3, va a la declaración catch y ya no se puede ejecutar en el hilo de fondo. Mi solución para esto es la siguiente:

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

(supongamos que tiene mContext y mUserAgent en el campo)

+0

Probablemente desee 'salir()' del Looper y 'join()' el hilo o usar 'wait()' y 'notify()'/'notifyAll()' para que se garantice que mUserAgent se modificará. Actualmente, el método puede regresar antes de que el hilo hijo actualice mUserAgent. – yingted

+0

Hola. Cambié la parte que dijiste. –

41

Hay una manera mucho más simple si usted está en Android 2.1 o superior. De acuerdo, esta no es exactamente la misma cadena de agente de usuario que devolvería una vista web, pero podría servirle lo suficientemente bien para sus propósitos.

Como una ventaja adicional para tirar desde la vista web, puede usar esto desde cualquier hilo (no solo el hilo de la IU).

Hay una propiedad del sistema llamada http.agent, que se puede usar para recuperar la cadena User-Agent.

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

Ver Programmatically get User-Agent String para obtener más detalles.

+6

Este no es el agente de usuario del navegador, que es lo que se solicitó. Sin embargo, funciona bien para muchos propósitos. – lilbyrdie

+0

Esta es ** la cadena de agente de usuario ** que WebView utilizará para identificarse ** al host ** de la página cargada actual en WebView. En caso de que necesite conectarse a través de HTTP Transport a cualquier host remoto, esta es la forma más elegante de identificarse como Android WebView. –

10

Desde Android 2.1 debe usar System.getProperty ("http.agent");

También no es necesario crear una vista web primero Y, esa es la ventaja, se puede usar dentro de un no-Uithread.

saludos steve

+3

Esta no es la respuesta a la pregunta. Esto le da al usuario ganet del dispositivo, no la vista web. – trante

1

Esta es una solución actualizada sobre la base de las respuestas anteriores que funciona cuando se compila para KitKat. Ahora la clase WebSettings es abstracta y la clase WebSettingsClassic ha sido eliminada.

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