Android中处理apple-touch-icon详解

苹果的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">

如果想支持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" 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">

加载网页,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

从上面的输出来看,基本上是后面(书写)的元素先打印出来,所以这个回调的缺陷如下

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代码中对应的回调。

代码如下:

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

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

返回的JSON数据

代码如下:

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

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

Google会改进么

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

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

代码如下:

<link rel="manifest" href="manifest.json">

在元数据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。

(0)

相关推荐

  • Android编程实现自动调整TextView字体大小以适应文字长度的方法

    本文实例讲述了Android编程实现自动调整TextView字体大小以适应文字长度的方法.分享给大家供大家参考,具体如下: package com.test.android.textview; import android.content.Context; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.TextView; public class CustomTextV

  • Android自定义控件实现icon+文字的多种效果

    今天给大家带来一个很简单但是很常用的控件ButtonExtendM,在开发中我们经常会用到图片加文字的组合控件,像这样: 以上图片都是从微信上截取的.(暂时没有找到icon在下,文字在上的例子) 下面我们通过一个控件来实现上下左右全部的样式,只需改动一个属性值即可改变icon的位置,是不是很方便,先看下demo效果图: 没错上图的三种不同的样式都是通过同一个控件实现的,下面我们看下代码 第一步 自定义属性  在res/values/目录下新建attrs.xml文件, 添加如下属性 <attr n

  • Android中正确使用字体图标(iconfont)的方法

    字体图标 字体图标是指将图标做成字体文件(.ttf),从而代替传统的png等图标资源. 使用字体图标的优点和缺点分别为: 优点: 1. 可以高度自定义图标的样式(包括大小和颜色),对于个人开发者尤其适用 2. 可以减少项目和安装包的大小(特别你的项目中有很多图片icon时,效果将是M级) 3. 几乎可以忽略屏幕大小和分辨率,做到更好的适配 4. 使用简单 -- 缺点:        1. 只能是一些简单的icon,不能代替如背景图.9图等资源 2. 一些需要文字说明的icon,图片资源将会是更好

  • android Textview文字监控(Textview使用方法)

    1.首先给用户添加一个textchangedlistener2.然后再写一个文字变化的监视器 复制代码 代码如下: mobile_et.addTextChangedListener(textWatcher); /**     * 实时监听用户输入的手机号,输入至最后一位后,计算折扣后的金额     */    TextWatcher textWatcher = new TextWatcher() { @Override        public void onTextChanged(CharS

  • Android开发技巧之像QQ一样输入文字和表情图像

    EditText和TextView一样,也可以进行图文混排.所不同的是,TextView只用于显示图文混排效果,而EditText不仅可显示,也可混合输入文字和图像,让我们先回顾一下图5.2所示的QQ聊天输入框,在输入框中可以同时输入文字和表情图像.实际上,这种效果在Android SDK中只需要几行代码就可以实现.为了使读者更有学习的冲动,先来欣赏一下即将实现的效果,如图5.16所示. 图5.16 在EditText控件中输入文字和图像 为了实现这个程序,首先来准备一些要用到的素材,也就是要在

  • android TextView设置中文字体加粗实现方法

    英文设置加粗可以在xml里面设置: 复制代码 代码如下: <SPAN style="FONT-SIZE: 18px">android:textStyle="bold"</SPAN> 英文还可以直接在String文件里面直接这样填写: 复制代码 代码如下: <string name="styled_text">Plain, <b>bold</b>, <i>italic</

  • Android实现仿微信tab高亮icon粘着手的滑动效果

    微信的主页分为3个tab,被选中的tab的tabwidget下面会有一个高亮的长条icon,而当切换tab页面的时候,这个icon不是等到tab切换完成后再出现在当前被选中的tab的tabwidget的下面,而是会随着viewpager滑动页面的动作也进行滑动,从前一个tabwidget滑到当前被选中的tabwidget,像viewpager一样有一种粘着你的手的效果,体验很赞.上个图: 本篇分析如何实现这个效果. 首先基本知识是,实现不同tab页之间可以滑动切换需要用到TabPageIndic

  • Android编程开发之TextView文字显示和修改方法(附TextView属性介绍)

    本文实例讲述了Android编程开发之TextView文字显示和修改方法.分享给大家供大家参考,具体如下: 一. 新建一个Activity 和 Layout 首先在layout文件夹中新建一个activity_main.xml,在新建工程的时候一般默认会新建此xml文件,修改其代码如下: activity_main.xml 代码 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" x

  • Android实现TextView中文字链接的4种方式介绍及代码

    Android 的实现TextView中文字链接的方式有很多种. 总结起来大概有4种: 1.当文字中出现URL.E-mail.电话号码等的时候,可以将TextView的android:autoLink属性设置为相应的的值,如 果是所有的类型都出来就是android:autoLink="all".当然也可以在java代码里 做,textView01.setAutoLinkMask(Linkify.ALL); 2.将要处理的文字写到一个资源文件,如string.xml,然后的java代码里

  • android app icon 图标大小尺寸

    在android程序中,在drawable中设置好图标后,但结果在小米2可没有显示出来,但在我自己的htc中和模拟器中显示正常.后来发现小米的dpi不一样. 后来发现,android为了适应不同的分辨率和dpi,加载了一系列的图标. LDPI (Low Density Screen,120 DPI),其图标大小为 36 x 36 px. MDPI (Medium Density Screen, 160 DPI),其图标大小为 48 x 48 px. HDPI (High Density Scre

随机推荐