Search code examples
javaandroidhttphttpurlconnectionfavicon

HttpURLConnection - "https://" vs. "http://"


I'm trying to get the favicon of the url the user enters, for example

_url = "google.com";

I use HttpUrlConnection to get the Bitmap of the favicon from the /favicon.ico extension from the host url.

        String faviconString = Uri.parse(_url).getHost() + "/favicon.ico";
        URL faviconUrl = null;
        Bitmap favicon = null;
        try
        {
            faviconString = "http://" + faviconString;
            faviconUrl = new URL(faviconString);
            HttpURLConnection connection = (HttpURLConnection) faviconUrl.openConnection();
            connection.setDoInput(true);
            connection.connect();
            favicon = BitmapFactory.decodeStream(connection.getInputStream());
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return favicon;

However, since the user probably won't specify http:// or https://, I would have to add it myself. The problem I'm having is that, if I add http:// in front of the url, everything would work fine, but for https://, some sites would return the favicon, others would just give me null. How do I find out which page uses https? Should I just add http:// for every case? Are there any websites that restricts to strictly https and would return null for using http?


Solution

  • Unless you use user2558882's idea or there is some other tool out in the wild that will just get a websites favicon for you, you're going to have to check both the http and https urls. There is no other way to do this. It is part of the difficulty of using the web.

    Perhaps looking at your code differently and breaking down what you're trying to do into smaller more manageable parts would be a bit better?

    public void getFavicon(String host) {
    
        URL httpUrl = this.getHttpUrl(host + "/favicon.ico");
    
        Bitmap favicon = this.getBitmap(httpUrl);
    
        if (favicon == null) {
    
            URL httpsUrl = this.getHttpsUrl(host + "/favicon.ico");
    
            favicon = this.getBitmap(httpsUrl);
        }
    
        if (favicon == null) {
    
            throw new FaviconMissingException("Unable to find favicon for host: " + host);
        }
    
        return favicon;
    }
    
    public URL getHttpUrl(String uri) throws MalformedURLException {
    
        // There are better ways of building a url then string concationation.
        return new URL("http://" + uri);
    }
    
    public URL getHttpsUrl(String uri) throws MalformedURLException {
    
        // There are better ways of building a url then string concationation.
        return new URL("https://" + uri);
    }
    
    public Bitmap getBitmap(URL url) {
    
        InputStream inputStream = getInputStream(url);
    
        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
    
        return bitmap
    }
    
    public InputStream getInputStream(URL url) {
    
        // Please use a real connection library like HTTPClient here!
        // HttpClient will handle timeouts, redirects, and things like that for you.
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
    
        return connection.getInputStream();
    }
    

    BTW, being concerned about one or two connections takes more time then writing the code to make two requests. I almost guarantee that google is making two requests as needed. And if it is good enough for google it is good enough for me.

    Finally, if you start to see that making two requests is really taking too much time, then do something about improving the performance.