苹果的Touch Icon相对我们都比较熟悉,是苹果为了支持网络应用(或者说网页)添加到桌面需要的图标,有了这些Touch Icon的网页链接更加和Native应用更相像了。由于苹果设备IPod,IPhone,IPad等设备广泛,很多网页都提供了touch icon这种图标资源。由于Android中并没有及早的有一份这样的标准,当我们想把网页添加到桌面时,仍然需要使用苹果的Touch Icon。 

Touch Icon

当我们想让一个网页比较完美地添加到桌面,通常情况下我们需要设置一个png图片文件作为apple-touch-icon。比如

  1. <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。

  1. <span style="font-family:Arial;font-size:14px;"><link rel="apple-touch-icon" href="touch-icon-iphone.png">
  2. <link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png">
  3. <link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png">
  4. <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中不需要进行视觉处理)。虽然有这些数据,我们可以进行处理,但是这其中是有问题的,就是我们不好确定文件的大小,来选择适合的图片。

举个例子,如下一个网页的源码,其中sizes的顺序不规律

  1. <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">
  2. <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.qiyipic.com/20130423143600/fix/H5-114x114.png">
  3. <link rel="apple-touch-icon-precomposed" sizes="57x57" href="http://www.qiyipic.com/20130423143600/fix/H5-57x57.png">
  4. <link rel="apple-touch-icon-precomposed" href="http://www.qiyipic.com/20130423143600/fix/H5-0x0.png"></span>

加载网页,onReceivedTouchIconUrl输出的日志

  1. <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">
  2. <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.qiyipic.com/20130423143600/fix/H5-114x114.png">
  3. <link rel="apple-touch-icon-precomposed" sizes="57x57" href="http://www.qiyipic.com/20130423143600/fix/H5-57x57.png">
  4. <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调用先后来决定使用哪个icon

3.回调中没有sizes属性值,不好确定使用哪个icon

4.如果我们选取质量最高的图片,然后进行适当压缩处理或许可以解决问题,但是将全部icon下载下来或者根据Head头信息总感觉不怎么好。

改进方法

既然WebView没有现成的方法满足我们的需求,只好自己来实现。其实实现方法还是比较简单地就是js脚本注入检测网页元素中得touch icon,返回json数据。

JavaScript方法

下面的JS代码所做的功能为查找所有为touch icon的link元素,包含正常的还标记为precomposed。然后将这些link元素的属性存入json数据,最后返回给Java代码中对应的回调。

  1. <span style="font-family:Arial;font-size:14px;">var touchIcons = [];
  2. function gatherTouchIcons(elements) {
  3. var normalTouchIconLength = elements.length;
  4. var currentElement;
  5. for (var i =0; i < normalTouchIconLength;i++) {
  6. currentElement = elements[i];
  7. var size;
  8. if (currentElement.hasAttribute('sizes')) {
  9. size = currentElement.sizes[0];
  10. } else {
  11. size = '';
  12. }
  13. var info = {'sizes':size, 'rel': currentElement.rel, 'href': currentElement.href};
  14. touchIcons.push(info);
  15. }
  16. }
  17.  
  18. function obtainTouchIcons() {
  19. normalElements = document.querySelectorAll("link[rel='apple-touch-icon']");
  20. precomposedElements = document.querySelectorAll("link[rel='apple-touch-icon-precomposed']");
  21. gatherTouchIcons(normalElements);
  22. gatherTouchIcons(precomposedElements);
  23. var info = JSON.stringify(touchIcons);
  24. window.app_native.onReceivedTouchIcons(document.URL, info);
  25. }
  26. obtainTouchIcons();</span>

Java代码

这里为了便于理解还是全部贴出了demo的源码,demo中当网页加载完成之后注入上面的js代码获取touch icon信息,然后返回给java的回调方法中。如果不清楚Java代码如何实现改进方案的,可以点击Java代码编写的Android应用如何实现安全

  1. <span style="font-family:Arial;font-size:14px;">package com.example.obtaintouchicon;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.InputStreamReader;
  8.  
  9. import android.app.Activity;
  10. import android.os.Bundle;
  11. import android.util.Log;
  12. import android.webkit.JavascriptInterface;
  13. import android.webkit.WebChromeClient;
  14. import android.webkit.WebView;
  15. import android.webkit.WebViewClient;
  16.  
  17. public class MainActivity extends Activity {
  18.  
  19. protected String LOGTAG = "MainActivity";
  20.  
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. WebView webView = new WebView(this);
  25. webView.getSettings().setJavaScriptEnabled(true);
  26. webView.setWebViewClient(new WebViewClient() {
  27. @Override
  28. public void onPageFinished(WebView view, String url) {
  29. super.onPageFinished(view, url);
  30. final String touchIconJsCode = getTouchIconJsCode();
  31. Log.i(LOGTAG , "onPageFinished url = " + url + ";touchIconJsCode=" + touchIconJsCode);
  32. view.loadUrl("javascript:" + touchIconJsCode);
  33. }
  34. });
  35. webView.addJavascriptInterface(new JsObject(), "app_native");
  36. webView.loadUrl("http://192.168.1.5:8000/html/touchicon.html");
  37. }
  38.  
  39. private class JsObject {
  40.  
  41. @JavascriptInterface
  42. public void onReceivedTouchIcons(String url, String json) {
  43. Log.i(LOGTAG, "onReceivedTouchIcons url=" + url + ";json=" + json);
  44. }
  45. }
  46.  
  47. private String getTouchIconJsCode() {
  48. StringBuilder total = new StringBuilder();
  49. InputStream inputStream = null;
  50. BufferedReader bufferReader = null;
  51. try {
  52. inputStream = getAssets().open("touchicon.js");
  53. bufferReader = new BufferedReader(new InputStreamReader(inputStream));
  54. String line;
  55. while ((line = bufferReader.readLine()) != null) {
  56. total.append(line);
  57. }
  58. } catch (FileNotFoundException e) {
  59. e.printStackTrace();
  60. } catch (IOException e) {
  61. e.printStackTrace();
  62. } finally {
  63. if (null != inputStream) {
  64. try {
  65. inputStream.close();
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. }
  71. return total.toString();
  72. }
  73. }</span>

返回的JSON数据

  1. <span style="font-family:Arial;font-size:14px;">[
  2. {
  3. "sizes":"72x72",
  4. "rel":"apple-touch-icon-precomposed",
  5. "href":"http://www.qiyipic.com/20130423143600/fix/H5-72x72.png"
  6. },
  7. {
  8. "sizes":"114x114",
  9. "rel":"apple-touch-icon-precomposed",
  10. "href":"http://www.qiyipic.com/20130423143600/fix/H5-114x114.png"
  11. },
  12. {
  13. "sizes":"57x57",
  14. "rel":"apple-touch-icon-precomposed",
  15. "href":"http://www.qiyipic.com/20130423143600/fix/H5-57x57.png"
  16. },
  17. {
  18. "sizes":"",
  19. "rel":"apple-touch-icon-precomposed",
  20. "href":"http://www.qiyipic.com/20130423143600/fix/H5-0x0.png"
  21. }
  22. ]</span>

我们可以对得到的JSON数据按照需要处理。

Google会改进么

答案是会,而且已经改进,但Google修改的不是onReceivedTouchIconUrl这个方法,而是Google正在推行自己的一套规则。

在Chrome上,Google增加了这样一个元素,这是Google提供的为网页程序定义元数据的方法。

  1. <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化了)。

  1. <span style="font-family:Arial;font-size:14px;">{
  2. "name": "Web Application Manifest Sample",
  3. "icons": [
  4. {
  5. "src": "launcher-icon-0-75x.png",
  6. "sizes": "36x36",
  7. "type": "image/png",
  8. "density": "0.75"
  9. },
  10. {
  11. "src": "launcher-icon-1x.png",
  12. "sizes": "48x48",
  13. "type": "image/png",
  14. "density": "1.0"
  15. },
  16. {
  17. "src": "launcher-icon-1-5x.png",
  18. "sizes": "72x72",
  19. "type": "image/png",
  20. "density": "1.5"
  21. },
  22. {
  23. "src": "launcher-icon-2x.png",
  24. "sizes": "96x96",
  25. "type": "image/png",
  26. "density": "2.0"
  27. },
  28. {
  29. "src": "launcher-icon-3x.png",
  30. "sizes": "144x144",
  31. "type": "image/png",
  32. "density": "3.0"
  33. },
  34. {
  35. "src": "launcher-icon-4x.png",
  36. "sizes": "192x192",
  37. "type": "image/png",
  38. "density": "4.0"
  39. }
  40. ],
  41. "start_url": "index.html",
  42. "display": "standalone",
  43. "orientation": "landscape"
  44. }</span>

但是由于目前,这种标准实施率相对比较低,所以我们还是需要使用苹果的touch icon。

源码下载http://pan.baidu.com/s/1dDD3gZZ

Android中处理Touch Icon的方案的更多相关文章

  1. Android中的Touch事件

    Android中的Touch事件处理 主要内容 Activity或View类的onTouchEvent()回调函数会接收到touch事件. 一个完整的手势是从ACTION_DOWN开始,到ACTION ...

  2. android中的Touch研究

    android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解. 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN-& ...

  3. Android中Touch事件分析--解决HorizontalScrollView滑动和按钮事件触发问题

    之前写过关于HorizontalScrollView滑动和按钮事件触发问题,但是不能所有的情况,最近几天一直在想这个问题,今天有一个比较好的解决思路,最终应用在项目里面效果也很好,首先说明一下功能: ...

  4. Android中线程间通信原理分析:Looper,MessageQueue,Handler

    自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...

  5. Android中的dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()

     dispatchTouchEvent (分发TouchEvent) 处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的.执行super.dispatc ...

  6. Android 编程下 Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  7. Android中直播视频技术探究之---桌面屏幕视频数据源采集功能分析

    一.前言 之前介绍了Android直播视频中一种视频源数据采集:摄像头Camera视频数据采集分析 中介绍了利用Camera的回调机制,获取摄像头的每一帧数据,然后进行二次处理进行推流.现在我们在介绍 ...

  8. Android 根据规划 Touch 分配和消费机制的事件

    Android 中与 Touch 事件相关的方法包含:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  9. iOS / Android 移动设备中的 Touch Icons

    上次转载了一篇<将你的网站打造成一个iOS Web App>,但偶然发现这篇文章的内容有些是错误的——准确来说也不是错误,只是不适合自半年前来的情况了(也可以说是iOS7 之后的时间)—— ...

随机推荐

  1. sqrt开平方算法的尝试,是的看了卡马克大叔的代码,我来试试用C#写个0x5f3759df和0x5f375a86跟System.Math.Sqrt到底哪个更强

    今天笔试遇到一个代码题,要求写一个开平方算法,回来发现了雷神之锤里的一段神代码: float Q_rsqrt( float number ) { long i; float x2, y; const ...

  2. struts2实现图片验证码

    生成图片验证码的主要工具类方法为: package com.yeting.fc.util; import java.awt.Color; import java.awt.Font; import ja ...

  3. 《一个民企CEO的职场阳谋》–读书总结(上)

    职场是一个战场,很多人几十年在这里战斗. 职场是一个熔炉,很多人大半生在这里修炼. 如果在办公室里得不到快乐,生活就不会快乐. 如果公司里头感觉不到幸福,人生就不会幸福.(以上四句来自老刘的博客) & ...

  4. 高级函数-decode

    decode(字段或计算表达式,           条件值1,结果值1,           条件值2,结果值2[,默认值]           )      if(字段或计算表达式 == 条件值1 ...

  5. C/C++ Quick Sort Algorithm

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50255069 快速排序算法,由C.A. ...

  6. 省赛i题/求1~n内全部数对(x,y),满足最大公约数是质数的对数

    求1~n内全部数对(x,y),gcd(x,y)=质数,的对数. 思路:用f[n]求出,含n的对数.最后用sum[n]求和. 对于gcd(x,y)=a(设x<=y,a是质数),则必有gcd(x/a ...

  7. Gym 100733J Summer Wars 题解:灵活运用扫描线的思想

    题意: 给你n个点,m个横着的线段.你能够横移这些线段,可是这些线段的相对位置不能改变.假设一个点,在它的正上方和和正下方都有线段(包含线段的终点).则这个点被视为被"屏蔽".问通 ...

  8. 使用XMLHttpRequest解析json

    不适用内函数或者promise的方式,可以在外部提取到json数据 <!DOCTYPE html> <html lang="en"> <head> ...

  9. VC++基于CXImage库实现缩略图

    一般的图像处理软件都对读入程序的图像文件建一个缩略图的列表,像ACDSee那样.笔者最近在做一个图像处理的项目,处理的原始数据就是图像文件.从项目一开始就想做一个缩略图,但一直苦于技术水平有限,且时间 ...

  10. 4.git "Could not read from remote repository.Please make sure you have the correct access rights."解决方案

    转自:https://zhiku8.com/git-could-not-read-from-remote-repository.html 我们在使用git clone 或其他命令的时候,有时候会遇到这 ...