2010-09-02 7 views
28

Existe-t-il un moyen de récupérer l'agent utilisateur du navigateur sans avoir WebView en activité?Récupérer l'agent utilisateur par programme

Je sais qu'il est possible d'obtenir via WebView:

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

Mais dans mon cas, je n'ai pas/besoin d'un objet WebView et je ne veux pas créer juste pour récupérer user- chaîne d'agent.

Répondre

41

Si vous ne ont que vous pouvez essayer de prendre comme ça

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

Modifier-

Le doc pour getUserAgentString() dit

Retour string-agent utilisateur de la WebView.

Donc, je ne pense pas que vous pouvez l'obtenir, sauf si vous en déclarez un. Quelqu'un me corrige si je me trompe

+1

Merci, cela fonctionne. Serait bien de le contourner sans créer d'objet, mais il semble que ce n'est pas vraiment possible ... – Laimoncijus

32

J'avais l'habitude d'utiliser solution proposé par DeRagan. Mais il s'est avéré que la création d'une seule instance WebView démarre un thread "WebViewCoreThread" qui reste en arrière-plan jusqu'à ce que l'application soit terminée par le système. Peut-être que ça ne consomme pas trop de ressources mais je ne l'aime pas quand même. Donc, j'utilise méthode légèrement différente maintenant, qui tente d'éviter la création de 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); 
    } 
} 

Il crée WebSettings exemple constructeur directement à l'aide du package visible et si ce n'est pas disponible pour une raison quelconque (par exemple, en raison de modifications de l'API dans le futur Android versions) - revient silencieusement à la solution "WebView-like".

MISE À JOUR

Comme indiqué par @Skywalker5446, à partir de Android 4.2/API 17, il existe une méthode statique publique pour obtenir la valeur de l'agent utilisateur par défaut. J'ai mis à jour mon code pour utiliser cette méthode sur les plates-formes prises en charge.

+1

Cette méthode échouera sur Android 4.2, 'WebSettings' est maintenant abstrait, bien qu'il y ait un' WebSettingsClassic', appelant des API privées toujours pas un moyen élégant, il va juste échouer à l'avenir et vous ne pouvez pas le réparer sans une mise à niveau. – neevek

+1

Dans Android 4.2/API 17, il existe une méthode statique publique pour obtenir cette valeur: WebSettings.getDefaultUserAgent (Context), ce qui vous permet d'ajouter une vérification de ce niveau d'API à cette astuce. –

+0

@ Skywalker5446 Merci pour les informations utiles, je vais mettre à jour ma réponse en conséquence. – Idolon

1

Grâce à la réponse d'Idolon, mon application pourrait traiter cela en arrière-plan.

Mais d'une certaine manière sur HTC Inspire 4G de AT & T qui fonctionne 2.3.3, il va à l'instruction catch et il ne peut plus être exécuté sur le thread d'arrière-plan. Ma solution pour cela est la suivante:

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

(supposons que vous avez mContext et mUserAgent dans le domaine)

+0

Vous voudrez probablement 'quitter()' Looper et 'rejoindre()' le thread ou utiliser 'wait()' et 'notify()'/'notifyAll()' pour que mUserAgent soit garanti pour être modifié. Actuellement, la méthode peut renvoyer avant la mise à jour du thread enfant mUserAgent. – yingted

+0

Bonjour. J'ai changé la partie que vous avez indiquée. –

41

Il y a une façon beaucoup plus simple si vous êtes sur Android 2.1 ou supérieur. Certes, il ne s'agit pas exactement de la même chaîne User Agent qu'une Webview retournera, mais elle pourrait vous servir assez bien pour vos besoins.

Comme un avantage supplémentaire à tirer de la vue web, vous pouvez l'utiliser à partir de n'importe quel thread (pas seulement le thread UI).

Il existe une propriété système appelée http.agent, qui peut être utilisée pour extraire la chaîne User-Agent.

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

Voir Programmatically get User-Agent String pour plus de détails.

+6

Ce n'est pas l'agent utilisateur du navigateur, ce qui a été demandé. Cela fonctionne bien à de nombreuses fins, cependant. – lilbyrdie

+0

Il s'agit du ** User-Agent String ** que WebView utilisera pour s'identifier ** à l'hôte ** de la page actuellement chargée dans WebView. Au cas où vous auriez besoin de vous connecter via un transport HTTP à un hôte distant, c'est le moyen le plus élégant de vous identifier comme Android WebView. –

10

Depuis Android 2.1, vous devez utiliser System.getProperty ("http.agent");

Vous n'avez pas non plus besoin de créer un WebView d'abord ET, c'est l'avantage, vous pouvez l'utiliser dans un non-uithread.

salutations steve

+3

Ce n'est pas la réponse à la question. Cela donne le ganet de l'utilisateur du périphérique, pas celui du Web. – trante

1

Ceci est une solution mise à jour en fonction des réponses précédentes qui fonctionne lorsque vous compilez pour KitKat. La classe WebSettings est maintenant abstraite et la classe WebSettingsClassic a été supprimée.

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