2013-09-20 4 views
9

Я пытаюсь получить фавиконки в URL пользователь вводит, напримерHttpURLConnection - "https: //" против "HTTP: //"

_url = "google.com"; 

Я использую HttpURLConnection, чтобы получить Bitmap от значка от расширения /favicon.ico от 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; 

Однако, так как пользователь, вероятно, не будет указывать http:// или https://, я бы добавить сам. Проблема, с которой я столкнулась, заключается в том, что если я добавлю http:// перед адресом, все будет работать нормально, но для https:// некоторые сайты вернут значок, другие просто дадут мне нуль. Как узнать, какая страница использует https? Должен ли я просто добавить http:// для каждого случая? Существуют ли какие-либо веб-сайты, которые ограничивают строго https и возвращают значение null для использования http?

+1

Это не очень надежный метод, так как значки могут быть определены внутри страницы, как это '<ссылка отн =«ярлык»HREF ="/a/different/path.ico "type =" image/x-icon "/>' – Emiel

+0

Есть ли другие способы предложить? 'WebIconDatabase' и' WebView.getFavicon() 'были бы идеальны, но' WebIconDatabase' устарел –

+0

Извините, что я не знаком с Android, но это звучит неплохо. – Emiel

ответ

4

Если вы не используете user2558882-х idea или есть какой-то другой инструмент в дикой природе, которые просто получить веб-сайт favicon для вас, вам нужно будет проверить URL-адрес и https-URL. Другого способа это не делать. Это часть сложности использования Интернета.

Возможно, вы посмотрите на свой код по-разному и сломаете то, что вы пытаетесь сделать в более компактных частях, немного лучше?

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, будучи обеспокоенным одним или двумя соединениями, занимает больше времени, а затем записывает код, чтобы сделать два запроса. Я почти гарантирую, что Google делает два запроса по мере необходимости. И если это достаточно хорошо для Google, это достаточно хорошо для меня.

И наконец, если вы начнете видеть, что выполнение двух запросов действительно занимает слишком много времени, тогда сделайте что-то для улучшения производительности.

1

Как насчет проверки того, возвращает ли сайт null или значок?

Я надеюсь, что это поможет вам

+0

Вы имеете в виду try 'https : // 'first и проверить, вернул ли favicon значение' null', а затем попробовал 'http: //'? Это было грубо вынуждено, я бы предпочел не продолжать этот путь, если это возможно. В конце концов, мне потребовалось бы открыть соединение в два раза меньше, чем идеальное. –

+0

thats right i'd было просто идея, что это не лучший способ ... –

4

Примечание: Я не уверен, насколько полезным мой ответ будет.

Вы можете захватить фавиконки с помощью Google:

http://www.google.com/s2/favicons?domain=stackoverflow.com 

возвращается:

enter image description here

Вы не должны указать http или https.

http://www.google.com/s2/favicons?domain=my.yorku.ca ===>> (https://my.yorku.ca) 

возвращается:

enter image description here

Но это не фактическая Favicon, что https://my.yorku.ca использования. Итак, я думаю, google возвращает значение по умолчанию для сайтов, которые не предоставляют доступ к своим знакам.

InputStream is = null; 

String urlPrefix = "http://www.google.com/s2/favicons?domain="; 

String _url = "google.com"; 

Bitmap favicon = null; 

try { 

    is = (InputStream) new URL(urlPrefix + _url).getContent(); 

} catch (MalformedURLException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

favicon = BitmapFactory.decodeStream(is); 

Вы можете фактически сохранить копию фавиконки по умолчанию и проверьте:

if (defaultBitmap.sameAs(favicon)) { 
    // favicon wasn't available 
} 
+0

Это классный подход, но для примера yorku 'yorku.com/favicon.ico' делает верните правильную иконку. Поэтому я, вероятно, по-прежнему буду использовать альтернативу '/ favicon.ico'. –

+0

@JasonHu Просто хочу убедиться, что вы используете действительные тестовые примеры. 'yorku.com/favicon.ico' недопустим, домен' http: // yorku.ca'. В моем ответе я использовал 'https: // my.yorku.ca'. Когда я попытался использовать 'https: // my.yorku.ca/favicon.ico', я получил нулевое значение. Подход google отлично подходит для 'yorku.ca'. – Vikram

+0

В моем комментарии я плохо использовал в своем тесте 'yorku.ca', который работал. Я думаю, что возврат «null» в порядке, если только в случае, когда использование '/ favicon.ico' возвращает' null' и 'google' возвращает то, что не является значком по умолчанию. Когда я вернусь «null», я просто использую значок по умолчанию на моем конце –

5
  URL url = new URL(downloadURL); 
      HttpURLConnection urlCon = null; 

      URL testUrlHttps = new URL(downloadURL); 
      if (testUrlHttps.getProtocol().toLowerCase().equals("https")) 
      { 
       trustAllHosts(); 
       HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); 
       https.setHostnameVerifier(DO_NOT_VERYFY); 
       urlCon = https; 
      } else 
      { 
       urlCon = (HttpURLConnection) url.openConnection(); 
      } 




add this method. May be it will help 



    private static void trustAllHosts() 
    { 
     // Create a trust manager that does not validate certificate chains 
     TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() 
     { 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() 
      { 
       return new java.security.cert.X509Certificate[] {}; 
      } 

      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException 
      { 
      } 

      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException 
      { 
      } 
     } }; 

     // Install the all-trusting trust manager 
     try 
     { 
      SSLContext sc = SSLContext.getInstance("TLS"); 
      sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
     } catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
+0

'testUrlHttps.getProtocol()' просто разбирает часть протокола строки 'downloadURL' в значительной степени, поэтому это не слишком помогает. Проблема была в основном в том случае, когда пользователь не указывает протокол (либо 'http', либо' https'), когда они вводят URL. –

1

Другой ответ, который даже «проще».

Просто заставьте пользователя ввести URL-адрес (включая протокол) для своего значка и подтвердить, что URL-адрес возвращает значок. Если нет, то отобразите ошибку проверки верности конечному пользователю.

Следуйте за гибкими принципами, выполняйте минимальное количество работ и смотрите, что работает. Если один план не работает, попробуйте что-то другое.

1

Попробуйте при запуске URL с «HTTPS»:

   TrustManager[] trustAllCerts = new TrustManager[] 
       { 
       new X509TrustManager() 
        { 
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } 
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {} 
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {} 
        } 
       }; 
       try 
       { 
        SSLContext sc = SSLContext.getInstance("SSL"); // "TLS" "SSL" 
        sc.init(null, trustAllCerts, null); 
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
        HttpsURLConnection.setDefaultHostnameVerifier( 
        new HostnameVerifier() 
        { 
         public boolean verify(String hostname, SSLSession session) { return true; } 
        }); 
       } 
       catch(Exception e) 
Смежные вопросы