Question

Is there a way to retrieve Browser's user-agent without having a WebView in activity?

I know it is possible to get it via WebView:

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

But in my case I don't have/need a webview object and I don't want to create it just for retrieving user-agent string.

Was it helpful?

Solution

If you don't have one you can try taking it like this

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

Edit-

The doc for getUserAgentString() says

Return the WebView's user-agent string.

So i don't think you can get it unless you declare one. Some one correct me if i am wrong

OTHER TIPS

There is a much simpler way if you are on Android 2.1 or above. Granted this isn't the exact same User Agent string that a webview would return, but might serve you well enough for your purposes.

As an additional advantage to pulling from web view, you can use this from any thread (not just the UI thread).

There is a system property called http.agent, which can be used to retrieve the User-Agent string.

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

See Programmatically get User-Agent String for more details.

I used to use solution proposed by DeRagan. But it turned out that creating a single WebView instance starts a thread "WebViewCoreThread" which stays on the background until application is terminated by the system. Maybe it doesn't consume too much resources but I don't like it anyway. So I use slightly different method now, which tries to avoid WebViewCoreThread creation:

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

It creates WebSettings instance directly using package-visible constructor and if that is not available for some reason (e.g. due to API changes in future Android versions) - silently falls back to "WebView-like" solution.

UPDATE

As pointed by @Skywalker5446, starting from Android 4.2/API 17, there is a public static method to get default user agent value. I've updated my code to use that method on the supported platforms.

Since Android 2.1 you should use System.getProperty("http.agent");

You also dont need to create a WebView first AND , thats the advantage, you can use it inside a non-uithread.

greetings steve

Thanks to Idolon's answer my app could process this in the background.

But somehow on HTC Inspire 4G from AT&T that runs 2.3.3, it goes to the catch statement and it can be no longer run on the background thread. My solution for this is the following:

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

(suppose you have mContext and mUserAgent in the field)

This is an updated solution based on previous answers that works when you compile for KitKat. Now the WebSettings class is abstract and the WebSettingsClassic class has been removed.

@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();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top