ti-enxame.com

Recuperar o User-Agent programaticamente

Existe uma maneira de recuperar o user agent do navegador sem ter um WebView em atividade?

Eu sei que é possível obtê-lo via WebView:

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

Mas, no meu caso, não tenho/preciso de um objeto de visualização na web e não quero criá-lo apenas para recuperar a sequência de agente do usuário.

36
Laimoncijus

Se você não tiver um, você pode tentar tomá-lo assim

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

Editar-

O documento para getUserAgentString() diz

Retorna a string do agente do usuário do WebView.

Então, eu não acho que você pode obtê-lo, a menos que você declare um. Alguém me corrija se eu estiver errado

54
DeRagan

Existe uma maneira muito mais simples se você estiver usando o Android 2.1 ou superior. Concedido que essa não é exatamente a mesma string do User Agent que uma visualização da web retornaria, mas pode atendê-lo suficientemente bem para seus propósitos) .

Como uma vantagem adicional de extrair da exibição da Web, você pode usá-lo em qualquer thread (não apenas no thread da interface do usuário).

Há uma propriedade do sistema chamada http.agent, que pode ser usada para recuperar a cadeia de caracteres User-Agent.

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

Consulte obter programaticamente a sequência do agente do usuário para obter mais detalhes.

56
Craig Russell

Eu costumava usar solução proposto por DeRagan. Porém, a criação de uma única instância WebView inicia um encadeamento "WebViewCoreThread" que permanece em segundo plano até que o aplicativo seja finalizado pelo sistema. Talvez ele não consuma muitos recursos, mas eu não gosto de qualquer maneira. Então, eu uso um método ligeiramente diferente agora, que tenta evitar a criação do 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);
  }
}

Ele cria a instância WebSettings diretamente usando o construtor visível do pacote e se isso não estiver disponível por algum motivo (por exemplo, devido a alterações da API no futuro Android)) - silenciosamente, volte para " Solução semelhante ao WebView ".

[~ # ~] atualização [~ # ~]

Conforme apontado por @ Skywalker5446 , a partir de Android 4.2/API 17, existe um método público estático para obter o valor padrão do agente do usuário. Atualizei meu código para use esse método nas plataformas suportadas.

35
Idolon

Desde Android 2.1, você deve usar System.getProperty ("http.agent");

Você também não precisa criar um WebView primeiro E, isso é a vantagem, você pode usá-lo dentro de um não-uithread.

saudações steve

10
JacksOnF1re

Esta é uma solução atualizada com base nas respostas anteriores que funciona quando você compila o KitKat. Agora a classe WebSettings é abstrata e a classe WebSettingsClassic foi removida.

@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
Monstieur

Graças à resposta de Idolon, meu aplicativo pode processar isso em segundo plano.

Mas, de alguma forma, no HTC Inspire 4G da AT&T, que executa 2.3.3, ele vai para a instrução catch e não pode mais ser executado no thread de segundo plano. Minha solução para isso é a seguinte:

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

(suponha que você tenha mContext e mUserAgent no campo)

1
st_bk