众所周知,Safari有一个“添加至主屏幕”的功能,其实就是在桌面添加了一个网页书签,本文讲述的是如何利用此功能实现桌面快捷电话。
一,主要用到的技术知识有以下几个(当然iPhone程序开发技能自然不可少)
1. JavaScript
3. Socket基本知识
4. Base64编码
二,基本原理
程序内部创建一个简单的Web站点,通过这个站点调用Safari,站点将自定义的Html页面返回给Safari,此时利用Safari的“添加至主屏幕”功能,将自定义的Html制作成桌面书签,当用户点击桌面图标时,则运行自定义的Javascript脚本拨打电话。
三,实现方法
1. 创建一个简易的Web站点,代码如下:
- - (void) startServer {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- int socketfd;
- socklen_t length;
- static struct sockaddr_in cli_addr;
- static struct sockaddr_in serv_addr;
- // Set up socket
- if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) {
- isServing = NO;
- return;
- }
- // Serve to a random port
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = 0;
- // Bind
- if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) {
- isServing = NO;
- return;
- }
- // Find out what port number was chosen.
- int namelen = sizeof(serv_addr);
- if (getsockname(listenfd, (struct sockaddr *)&serv_addr, (void *) &namelen) < 0) {
- close(listenfd);
- isServing = NO;
- return;
- }
- chosenPort = ntohs(serv_addr.sin_port);
- // Listen
- if(listen(listenfd, 64) < 0) {
- isServing = NO;
- return;
- }
- // Respond to requests until the service shuts down
- while (isServing) {
- length = sizeof(cli_addr);
- if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) {
- isServing = NO;
- return;
- }
- [self handleWebRequest:[NSNumber numberWithInt:socketfd]];
- }
- [pool release];
- }
- - (void) handleWebRequest:(NSNumber *)fdNum {
- int fd = [fdNum intValue];
- NSLog(@"handleWebRequest: %@", fdNum);
- }
2. 制作Html页面模板,代码如下,请注意代码中$XXX$标识串,主要在程序中将其替换成实际内容
- <!DOCTYPE html>
- <html>
- <head>
- <meta content="yes" name="apple-mobile-web-app-capable" />
- <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
- <link rel="apple-touch-icon-precomposed" href="$TOUCH_ICON_URL$" mce_href="$TOUCH_ICON_URL$" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
- <mce:style type="text/css"><!--
- body
- {position:relative;
- margin:0;
- min-height:416px;
- font-family:helvetica,sans-serif;
- }
- --></mce:style><style type="text/css" mce_bogus="1">body
- {position:relative;
- margin:0;
- min-height:416px;
- font-family:helvetica,sans-serif;
- }</style>
- <mce:script type="text/javascript"><!--
- var timerInit = 0;
- addEventListener("load", function() { timerInit = setTimeout(InitPage, 0.2); }, false);
- function InitPage(){
- clearTimeout(timerInit);
- window.scrollTo(0,1);
- document.body.ontouchstart = function(e) {
- window.scrollTo(0,1);
- e.preventDefault();
- };
- document.body.ontouchmove = function(e) {
- e.preventDefault();
- };
- document.body.ontouched = function(e) {
- e.preventDefault();
- };
- if (window.navigator.standalone == true) {
- var lnk = document.getElementById("qbt");
- var evt = document.createEvent('MouseEvent');
- evt.initMouseEvent('click');
- lnk.dispatchEvent(evt);
- }
- else{
- ip = document.getElementById("ip");
- its = document.getElementById("it").style;
- ip.style.position = "absolute";
- ip.style.top = window.innerHeight - 320 + "px";
- ip.style.visibility = "visible";
- ip.innerHTML = '<img src="$INSTRUCTION_IMG_URL$" mce_src="$INSTRUCTION_IMG_URL$" width="320" height="320"/>';
- its.position = "absolute";
- its.top = window.innerHeight - 114 + "px";
- its.left = 112 + "px";
- its.visibility = "visible";
- }
- }
- // --></mce:script>
- <title>$TITLE$</title></head>
- <body bgcolor="#ffffff"><a href="$URL$" mce_href="$URL$" id="qbt" style="display: none;" mce_style="display: none;"> </a>
- <div id="ip" style="visibility:hidden;z-index:1;" mce_style="visibility:hidden;z-index:1;"></div>
- <div id="it" style="font-size:14px;color:#000055;visibility:hidden;z-index:2;" mce_style="font-size:14px;color:#000055;visibility:hidden;z-index:2;">$INSTRUCTIONTXT$</div>
- </body></html>
3. 程序调用Safari
(1) 使用[[UIApplication sharedApplication]openURL:]方法,url地址为自定义的web站点,如http://localhost:端口号。
(2) 在Web站点中的handleWebRequest方法中,将自定义的html内容发送给safari
4. 程序在info.plist中注册自定义schema,此处主要解决浏览器拨打时会弹出确认对话框,所以先打开我们的程序,通过程序去拨打电话,代码如下:
- - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
- if ([[url scheme] isEqualToString:@"quickdial"]) {
- NSString *hostName = [url host];
- if ([hostName isEqualToString:@"tel"]) {
- NSString *phoneNo = [url query];
- [[UIApplication sharedApplication]openURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel://%@", phoneNo]]];
- }
- }
- return NO;
- }