Android中處理Touch Icon的方案

goopen123 9年前發布 | 53K 次閱讀 Android Android開發 移動開發

蘋果的Touch Icon相對我們都比較熟悉,是蘋果為了支持網絡應用(或者說網頁)添加到桌面需要的圖標,有了這些Touch Icon的網頁鏈接更加和Native應用更相像了。由于蘋果設備IPod,IPhone,IPad等設備廣泛,很多網頁都提供了touch icon這種圖標資源。由于Android中并沒有及早的有一份這樣的標準,當我們想把網頁添加到桌面時,仍然需要使用蘋果的Touch Icon。

Touch Icon

當我們想讓一個網頁比較完美地添加到桌面,通常情況下我們需要設置一個png圖片文件作為apple-touch-icon。比如


  • <link rel="apple-touch-icon" href="/custom_icon.png"> 
    </td> </tr> </tbody> </table>

    如果想支持IPhone和IPad,我們需要使用sizes屬性來制定多個圖片,默認sizes的值為60 x 60。

    <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">


    在IOS7之前,蘋果系統會對添加到桌面的圖標進行圓角化等視覺上的處理,為了不讓其處理,我們可以使用apple-touch-icon-precomposed來作為rel的值實現。

    更多關于Touch Icon的信息,可以訪問 水果開發者網站 了解更多。

    Android中有缺陷的實現

    在Android WebView提供了處理Touch Icon的回調,onReceivedTouchIconUrl(WebView view, String url,boolean precomposed)該方法返回了對我們有用的touch icon的url,和是否為預組合(在IOS中不需要進行視覺處理)。雖然有這些數據,我們可以進行處理,但是這其中是有問題的,就是我們不好確定文件的大小,來選擇適合的圖片。

    舉個例子,如下一個網頁的源碼,其中sizes的順序不規律

    <link rel="apple-touch-icon-precomposed" sizes="72x72" >
    <link rel="apple-touch-icon-precomposed" sizes="114x114" >
    <link rel="apple-touch-icon-precomposed" sizes="57x57" >
    <link rel="apple-touch-icon-precomposed"  >


    加載網頁,onReceivedTouchIconUrl輸出的日志

    I/MainActivity( 6995): onReceivedTouchIconUrl url=http://www.qiyipic.com/20130423143600/fix/H5-0x0.png;precomposed=true
    I/MainActivity( 6995): onReceivedTouchIconUrl url=http://www.qiyipic.com/20130423143600/fix/H5-57x57.png;precomposed=true
    I/MainActivity( 6995): onReceivedTouchIconUrl url=http://www.qiyipic.com/20130423143600/fix/H5-114x114.png;precomposed=true
    I/MainActivity( 6995): onReceivedTouchIconUrl url=http://www.qiyipic.com/20130423143600/fix/H5-72x72.png;precomposed=true


    從上面的輸出來看,基本上是后面(書寫)的元素先打印出來,所以這個回調的缺陷如下

    • 由于Touch Icon url地址沒有硬性規定,不能根據url包含某些尺寸來判斷使用哪個icon
    • 由于網頁編寫touch icon元素相對隨意,不能根據onReceivedTouchIconUrl調用先后來決定使用哪個icon
    • 回調中沒有sizes屬性值,不好確定使用哪個icon
    • 如果我們選取質量最高的圖片,然后進行適當壓縮處理或許可以解決問題,但是將全部icon下載下來或者根據Head頭信息總感覺不怎么好。

    改進方法

    既然WebView沒有現成的方法滿足我們的需求,只好自己來實現。其實實現方法還是比較簡單地就是js腳本注入檢測網頁元素中得touch icon,返回json數據。

    JavaScript方法

    下面的JS代碼所做的功能為查找所有為touch icon的link元素,包含正常的還標記為precomposed。然后將這些link元素的屬性存入json數據,最后返回給Java代碼中對應的回調。

    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();</pre>

    Java代碼

    這里為了便于理解還是全部貼出了demo的源碼,demo中當網頁加載完成之后注入上面的js代碼獲取touch icon信息,然后返回給java的回調方法中。如果不清楚Java和JavaScript交互,可以訪問 Android中Java和JavaScript交互 了解更多。

    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("

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

    返回的JSON數據

         
    
    

    [ { "sizes":"72x72", "rel":"apple-touch-icon-precomposed", "href":"

    我們可以對得到的JSON數據按照需要處理。

    Google會改進么

    答案是會,而且已經改進,但Google修改的不是onReceivedTouchIconUrl這個方法,而是Google正在推行自己的一套規則。

    在Chrome上,Google增加了這樣一個元素,這是Google提供的為網頁程序定義元數據的方法。


    <link rel="manifest" href="manifest.json"> 
    </td> </tr> </tbody> </table>

    在元數據json中,你可以自定義title,起始頁,程序是橫屏還是豎屏展示。一個簡單地json實例如下,這里我們可以看到其中icons 中存在多個類似touch icon的圖標,src代表圖標路徑,sizes代表大小,type就是mimetype,density指的是Android中的屏幕密度(這樣更加 Android化了)。

    {
      "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"
    }


    關于Google這套新的標準,可以參考 Add to Homescreen

    但是由于目前,這種標準實施率相對比較低,所以我們還是需要使用蘋果的touch icon。

    推薦閱讀

    源碼下載

        <p>
            <br />
        </p>
    </div>
    

    </div> 來自:http://droidyue.com/blog/2015/01/18/deal-with-touch-icon-in-android/

     本文由用戶 goopen123 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
  • sesese色