蘋果的Touch Icon相對咱們都比較熟悉,是蘋果爲了支持網絡應用(或者說網頁)添加到桌面須要的圖標,有了這些Touch Icon的網頁連接更加和Native應用更相像了。因爲蘋果設備IPod,IPhone,IPad等設備普遍,不少網頁都提供了touch icon這種圖標資源。因爲Android中並無及早的有一份這樣的標準,當咱們想把網頁添加到桌面時,仍然須要使用蘋果的Touch Icon。
Touch Icon
javascript
當咱們想讓一個網頁比較完美地添加到桌面,一般狀況下咱們須要設置一個png圖片文件做爲apple-touch-icon。好比html
<span style="font-family:Arial;font-size:14px;"><link rel="apple-touch-icon" href="/custom_icon.png"></span>
若是想支持IPhone和IPad,咱們須要使用sizes屬性來制定多個圖片,默認sizes的值爲60 x 60。java
<span style="font-family:Arial;font-size:14px;"><link rel="apple-touch-icon" href="touch-icon-iphone.png"> <link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png"> <link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png"> <link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad-retina.png"></span>
在IOS7以前,蘋果系統會對添加到桌面的圖標進行圓角化等視覺上的處理,爲了避免讓其處理,咱們可使用apple-touch-icon-precomposed來做爲rel的值實現。
更多關於Touch Icon的信息,能夠訪問 水果開發者網站 瞭解更多。
Android中有缺陷的實現
在Android WebView提供了處理Touch Icon的回調,onReceivedTouchIconUrl(WebView view, String url,boolean precomposed)該方法返回了對咱們有用的touch icon的url,和是否爲預組合(在IOS中不須要進行視覺處理)。雖然有這些數據,咱們能夠進行處理,可是這其中是有問題的,就是咱們很差肯定文件的大小,來選擇適合的圖片。
android
舉個例子,以下一個網頁的源碼,其中sizes的順序不規律web
<span style="font-family:Arial;font-size:14px;"><link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.qiyipic.com/20130423143600/fix/H5-72x72.png"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.qiyipic.com/20130423143600/fix/H5-114x114.png"> <link rel="apple-touch-icon-precomposed" sizes="57x57" href="http://www.qiyipic.com/20130423143600/fix/H5-57x57.png"> <link rel="apple-touch-icon-precomposed" href="http://www.qiyipic.com/20130423143600/fix/H5-0x0.png"></span>
加載網頁,onReceivedTouchIconUrl輸出的日誌json
<span style="font-family:Arial;font-size:14px;"><link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.qiyipic.com/20130423143600/fix/H5-72x72.png"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.qiyipic.com/20130423143600/fix/H5-114x114.png"> <link rel="apple-touch-icon-precomposed" sizes="57x57" href="http://www.qiyipic.com/20130423143600/fix/H5-57x57.png"> <link rel="apple-touch-icon-precomposed" href="http://www.qiyipic.com/20130423143600/fix/H5-0x0.png"></span>
從上面的輸出來看,基本上是後面(書寫)的元素先打印出來,因此這個回調的缺陷以下
安全
1.因爲Touch Icon url地址沒有硬性規定,不能根據url包含某些尺寸來判斷使用哪一個icon網絡
2.因爲網頁編寫touch icon元素相對隨意,不能根據onReceivedTouchIconUrl調用前後來決定使用哪一個iconapp
3.回調中沒有sizes屬性值,很差肯定使用哪一個iconiphone
4.若是咱們選取質量最高的圖片,而後進行適當壓縮處理或許能夠解決問題,可是將所有icon下載下來或者根據Head頭信息總感受不怎麼好。
改進方法
既然WebView沒有現成的方法知足咱們的需求,只好本身來實現。其實實現方法仍是比較簡單地就是js腳本注入檢測網頁元素中得touch icon,返回json數據。
JavaScript方法
下面的JS代碼所作的功能爲查找全部爲touch icon的link元素,包含正常的還標記爲precomposed。而後將這些link元素的屬性存入json數據,最後返回給Java代碼中對應的回調。
<span style="font-family:Arial;font-size:14px;">var touchIcons = []; function gatherTouchIcons(elements) { var normalTouchIconLength = elements.length; var currentElement; for (var i =0; i < normalTouchIconLength;i++) { currentElement = elements[i]; var size; if (currentElement.hasAttribute('sizes')) { size = currentElement.sizes[0]; } else { size = ''; } var info = {'sizes':size, 'rel': currentElement.rel, 'href': currentElement.href}; touchIcons.push(info); } } function obtainTouchIcons() { normalElements = document.querySelectorAll("link[rel='apple-touch-icon']"); precomposedElements = document.querySelectorAll("link[rel='apple-touch-icon-precomposed']"); gatherTouchIcons(normalElements); gatherTouchIcons(precomposedElements); var info = JSON.stringify(touchIcons); window.app_native.onReceivedTouchIcons(document.URL, info); } obtainTouchIcons();</span>
Java代碼
這裏爲了便於理解仍是所有貼出了demo的源碼,demo中當網頁加載完成以後注入上面的js代碼獲取touch icon信息,而後返回給java的回調方法中。若是不清楚Java代碼如何實現改進方案的,能夠點擊Java代碼編寫的Android應用如何實現安全
<span style="font-family:Arial;font-size:14px;">package com.example.obtaintouchicon; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; public class MainActivity extends Activity { protected String LOGTAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webView = new WebView(this); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); final String touchIconJsCode = getTouchIconJsCode(); Log.i(LOGTAG , "onPageFinished url = " + url + ";touchIconJsCode=" + touchIconJsCode); view.loadUrl("javascript:" + touchIconJsCode); } }); webView.addJavascriptInterface(new JsObject(), "app_native"); webView.loadUrl("http://192.168.1.5:8000/html/touchicon.html"); } private class JsObject { @JavascriptInterface public void onReceivedTouchIcons(String url, String json) { Log.i(LOGTAG, "onReceivedTouchIcons url=" + url + ";json=" + json); } } private String getTouchIconJsCode() { StringBuilder total = new StringBuilder(); InputStream inputStream = null; BufferedReader bufferReader = null; try { inputStream = getAssets().open("touchicon.js"); bufferReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferReader.readLine()) != null) { total.append(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return total.toString(); } }</span>
返回的JSON數據
<span style="font-family:Arial;font-size:14px;">[ { "sizes":"72x72", "rel":"apple-touch-icon-precomposed", "href":"http://www.qiyipic.com/20130423143600/fix/H5-72x72.png" }, { "sizes":"114x114", "rel":"apple-touch-icon-precomposed", "href":"http://www.qiyipic.com/20130423143600/fix/H5-114x114.png" }, { "sizes":"57x57", "rel":"apple-touch-icon-precomposed", "href":"http://www.qiyipic.com/20130423143600/fix/H5-57x57.png" }, { "sizes":"", "rel":"apple-touch-icon-precomposed", "href":"http://www.qiyipic.com/20130423143600/fix/H5-0x0.png" } ]</span>
咱們能夠對獲得的JSON數據按照須要處理。
Google會改進麼
答案是會,並且已經改進,但Google修改的不是onReceivedTouchIconUrl這個方法,而是Google正在推行本身的一套規則。
在Chrome上,Google增長了這樣一個元素,這是Google提供的爲網頁程序定義元數據的方法。
<span style="font-family:Arial;font-size:14px;"><link rel="manifest" href="manifest.json"></span>
在元數據json中,你能夠自定義title,起始頁,程序是橫屏仍是豎屏展現。一個簡單地json實例以下,這裏咱們能夠看到其中icons中存在多個相似touch icon的圖標,src表明圖標路徑,sizes表明大小,type就是mimetype,density指的是Android中的屏幕密度(這樣更加Android化了)。
<span style="font-family:Arial;font-size:14px;">{ "name": "Web Application Manifest Sample", "icons": [ { "src": "launcher-icon-0-75x.png", "sizes": "36x36", "type": "image/png", "density": "0.75" }, { "src": "launcher-icon-1x.png", "sizes": "48x48", "type": "image/png", "density": "1.0" }, { "src": "launcher-icon-1-5x.png", "sizes": "72x72", "type": "image/png", "density": "1.5" }, { "src": "launcher-icon-2x.png", "sizes": "96x96", "type": "image/png", "density": "2.0" }, { "src": "launcher-icon-3x.png", "sizes": "144x144", "type": "image/png", "density": "3.0" }, { "src": "launcher-icon-4x.png", "sizes": "192x192", "type": "image/png", "density": "4.0" } ], "start_url": "index.html", "display": "standalone", "orientation": "landscape" }</span>
可是因爲目前,這種標準實施率相對比較低,因此咱們仍是須要使用蘋果的touch icon。