诡异的iOS keep-alive bug

https://bugs.webkit.org/show_bug.cgi?id=155632

去年12月发现,偶发性,各种Charles抓包、rvictl流量复制等方式来定位分析,还恶补了TCP协议,都没找到原因,只是看上去觉得iOS这边处理HTTP请求的方式怪怪的。

终于尘埃落定,服务端根据UA识别出iOS,关掉HTTP的Keep-Alive功能来规避。

keep-alive是HTTP协议里面的

keepalive是TCP协议里面的

HTTP协议通过头部的 connection: keep-alive 来通知两端TCP建立一个keepalive链接,在keepalive有效期内,不需要重复3次握手动作,不需要重新慢启动

 

iOS抓包新姿势 – rvictl

最近遇到一个诡异的问题,出现在特殊网络情况下,一旦劫持抓包就无法重现,怎么破?

Google告诉我们,iOS有一个rvictl的神器。

rvictl总共就3个参数

  • -l 显示当前活跃设备
  • -s 开始监听
  • -x 结束监听

其原理是将iOS设备的流量,像打日志一样复制一份到Mac上,在Mac上再通过Wireshark就能进行分析。这种做法,不像代理,不会干扰iOS设备正常的网络访问。

步骤

1.将iPhone通过数据线,连上Mac,并打开iTunes,复制设备UDID。

2.打开Terminal,输入  rvictl -s 设备UDID

3.打开Wireshark,在捕获选项里面选择rvi0这个设备,这个时候,iPhone所有TCP和UDP流量,都会打印到Mac上。

4.在Wireshark里面输入合适的过滤器,便于追踪目标流量。

iOS9.1终于可以关闭讨厌的300ms延迟了

通过viewprot配置来关闭,FastClick快要完成历史使命了。

Fast-Tap on iOS

On Safari for iOS, the 350 ms wait time to detect a second tap has been removed to create a “fast-tap” response. This is enabled for pages that declare a viewport with either width=device-width or user-scalable=no. Authors can also opt in to fast-tap behavior on specific elements by using the CSS touch-action property, using the manipulation value.

See http://www.w3.org/TR/pointerevents/#the-touch-action-css-property.

 

完整特性更新列表

https://developer.apple.com/library/prerelease/mac/releasenotes/General/WhatsNewInSafari/Articles/Safari_9_1.html

PushPlugin-为iOS的Hybird App提供APNS服务

APNS是什么?

APNS是iOS生态下面的推送机制。其原理是APP启动的时候,向苹果注册,并获得一个唯一token,然后不论app是否继续在运行,都可以通过调用苹果的APNS服务,来向持有token的设备推送消息,例如顶部的通知。

之前有SSE了,为什么还要APNS?

一开始我也分不清,后来发现,APNS可以在应用关闭的时候,通过iOS系统的通知栏,推送消息给用户,让用户重新进入app中执行某些事情。而这些,是SSE做不到的,SSE仅仅是一套消息机制,必须有app运行的时候才有效。

说了这么久,怎么用?

参考这篇文章:https://github.com/phonegap-build/PushPlugin#automatic_installation

使用方法:

1、安装PushPlugin插件

cordova plugin add https://github.com/phonegap-build/PushPlugin.git

2、配置插件

这个是我把官方的例子,做了一下AMD的封装,使用的方法如下。

然后,就没有然后了。留意tokenHandler里面的结果,收集下来,然后就可以给服务端。app启动后,就可以随时接收服务端的信息了。

看上去很简单,为什么用了这么多时间?

嗯,APP端很简单,但是服务端涉及到各种证书,有点弄不清,然后官方的文档又都是全英,半桶水英语看得够呛。

PushPlugin为我们准备了Example目录,里面的server端有ruby的脚本供我们测试。

测试前的准备:

  1. Ruby的环境
  2. 上面已经装好PushPlugin的APP
  3. 安装pushmeup  sudo gem install pushmeup

接下来就是看得我头晕的生成pem的过程。

  1. 我也懒得翻译了,直接参考这篇文章,获得ck.pem文件。
  2. 编辑Example/server/pushAPNS.rb,配置里面的pem、pem密码和接收消息设备的token。
  3. 执行脚本,向设备推送消息。 ruby pushAPNS.rb

PushPlugin使用小结

客户端安装PushPlugin,并配置好register的时机,同时,在获取到token之后,将token上报给服务端。

服务端按照苹果的要求,配置好各种证书后,向持有token的设备下达消息。

不论app是否仍在运行,设备都将会受到这条消息。

iOS开发者证书-2015年中文版

我们都知道,制作一款iOS的App需要iOS的开发者证书。在Apple的开发者网站上面,有一个栏目是‘Certificates, Identifiers & Profiles’。这三个东西,对于一开始接触的人,实在是一头雾水。

Certificates 证书,如开发者证书

  • Development
    • iOS App Development 开发者证书
    • Apple Push Notification Service SSL(Sandbox)
  • Production
    • App Store and AD Hoc 发布证书
    • Apple Push Notification service SSL (Production)
    • Pass Type ID Certificate
    • Website Push ID Certificate
    • VoIP Services Certificate
    • Apple Pay Certificate

在证书这栏,我们主要关注开发者证书和发布证书这两个。

开发者证书是和Mac相关联的,由Mac上面的‘证书管理’请求证书,生成一个*.certSigningRequrest的文件。将该文件提交到开发者网站上面,即可生成对应的开发者账号证书。

发布证书则是发布应用的时候才需要的。

Identifiers 唯一识别码

  • App IDs App的唯一ID,也就是Xcode里面的Bundle-id
  • Pass Type IDs
  • Website Push IDs
  • iCloud Containers
  • App Groups
  • Merchant IDs

这里,我们暂时只需要关注App IDs,为我们的应用创建一个Bundle-id,并且配置对应的一些功能(部分功能需要再申请对应的证书文件)。

Devices 设备

  • All 全部

硬件这栏没有二级菜单,里面显示的全部测试设备的UDID,一个开发者账号可以有100个UDID。

通过Ad-hoc方式进行测试分发,需要收集测试设备的UDID,测试设备才能安装上。

之前pgyer.com提供她们的企业证书,供第三方来二次打包,并以企业分发的形式进行供外部用户进行测试。但在Apple收购了TestFlight之后,这部分策略被收紧了。

现在进行分发测试,要么自己买企业证书,要么自己收集UDID,要么走苹果的TestFlight外部测试的流程(这个测试发布,也是要经过苹果审核的)。

Provisioning Profiles 描述文件

  • All
  • Development 开发描述文件
    • iOS App Development 开发者证书描述文件,用来关联App ID、开发者证书、测试硬件之间的关系
  • Distribution 分发描述文件
    • App Store 应用市场的描述文件, 用来关联App ID、发布证书之间的关系
    • Ad Hoc 测试分发的描述文件,用来关联App ID、发布证书、测试硬件之间的关系

晕了没?反正我是晕了。总结以下就是:

  • 需要一个开发证书,这个证书是和Mac\Xcode有关系的。
  • 需要一个App ID,来作为你的软件的唯一标示。
  • 需要一个描述文件,这个文件是用来绑定你的证书和App ID的。

还有

刚才上面的这些东西,都是在开发者网站上面进行配置的,然后每次变更,最后Xcode都要关掉重启,以便能正确加载最新的关系。

然后,Xcode自己也会生成、维护一套证书关系,所以,一个不小心,你在Apple开发者网站上面的各种证书描述文件会满天飞。

再然后,上面提到的是单个开发者的,如果是多个开发者,同时使用一个开发者账号,那又会出现各种诡异的证书描述文件错误问题。

给iOS的WebView添加远程调试

2015-01-16更新:

最新版Cordova默认已经开启了远程调试,只要是通过Xcode来安装到设备上面的应用,都可以在Safari设置里面打开远程调试。而release出来ipa之后,则无法再使用远程调试,这个可能也是为了安全因素吧。


在Xcode中找到AppDelegate.m文件

定位到 didFinishLaunchingWithOptions 代码块中。

添加如下代码:

此时Xcode会报错,提示

no known class method for selector ‘_enableRemoteInspector

错误原因是该方法是iOS的一个私有API,从iOS5开始,Xcode项目新增了Automatic Reference Counting检查项,我们只需要关闭它,就可以正常编译了。

在工程属性中 -》 Build Settings -》 Object-C Automatic Reference Counting,将其设置为No即可。

iOS自定义键盘搜索键

之前知道HTML5的input属性,新增了一种type=search。当系统焦点在input[type=search]元素上时,iOS会自动更改键盘的确认按键为搜索,且按下后自动收齐键盘。

但是我尝试了一次,一直不成功,最后发现,原来是姿势不对。

input[type=search]必须放在一个form标签中,才会更改iOS键盘的效果。

效果如下图:

input[type=search]

还能通过一些webkit私有属性,自定义这个搜索框的样式,例如右边的XX,或者placeholder字体颜色等。

更多玩法,可以这篇文章:http://css-tricks.com/webkit-html5-search-inputs/

 

Design For Mobile Web

这两天专门制作了一个手机页面,现在分享一下里面常用的一些技巧。

通过viewport来匹配设备宽度

网上常见的做法:

上面这段代码,源自Google的Best Practices for Web Apps,但在实际使用过程中,并不能完全适应iOS、Android平台,至于WP,我的注意力暂时还没在它身上。

今天终于找个一个兼容Android和iOS的方法了。

这样,设计Mobile Web页面的时候,只需要按照640px的宽度进行设计就可以了。测试结果是Android 2.2+自带浏览器、iOS5+自带浏览器、Chrome移动版、Firebox移动版和UC8+以上版本皆能完美自适应。

PS:

  • 刚才搜索了一下viewport这个概念博大高深,里面还涉及到dpi等,我这里只是一种偷懒的方法。
  • viewport和响应式设计理念不同,响应式设计是一套html结构适配全平台,而viewport仅仅是给移动平台使用,并不打算兼容PC平台,如需兼容PC浏览器,需要另外写判断。

iOS中的WebApp

html5有多强大?看看之前Facebook在iOS上面的客户端就知道。

这里贴一些制作WebApp可能会需要用到的代码。

例如最常见的,隐藏导航栏,隐藏菜单栏等,不过这类效果,必须要用户把Web添加到主屏幕上,并且通过主屏幕上面的图标进入才生效。

同时,如果从WebApp中跳到了外部的浏览器或者其他软件,想再次返回到WebApp的时候,必须重新打开,不能够保存上次的访问结果。估计这事应该有解决方法。

导航了太占位了,如何在浏览器中就隐藏掉呢

就这么简单,当页面加载成功的时候,页面自动向上滚动,导航了就看不到了,第一页的高度就多了50px。

下面的菜单栏也很占位,如何隐藏?

404,这个,还真没找到方法…