热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS保存app内容到手机桌面

http:www.cocoachina.comios2015030911270.html今天,我发现淘宝手机app可以把用户喜欢的店铺保存到app的桌面上,感觉很神奇,研究了下怎么

http://www.cocoachina.com/ios/20150309/11270.html

今天,我发现淘宝手机app可以把用户喜欢的店铺保存到app的桌面上,感觉很神奇,研究了下怎么做,并记录下来顺便分享下心得。附上demo地址

下面是实际效果:
安装描述文件

《iOS保存app内容到手机桌面》

safari生成webclip

《iOS保存app内容到手机桌面》

这种效果就是苹果的webclip,app上要生成它主要有2种方式。

通过安装描述文件的方式生成webclip

  • 使用iphone configuration utility生成一个webclip描述文件。

下载iphone configuration utility后配置一个描述文件,导出即可。

  • 使用safari安装这个描述文件。

使用[UIApplication sharedApplication] openURL:的方式无法直接打开描述文件,UIWebView也不支持打开这种文件类型。

safari是可以直接安装描述文件的,但是safari和应用是2个独立的沙盒,所以这里需要解决应用和safari共享文件的问题。这里使用的思路是把app作为一个服务器,让safari访问这个服务器获取到描述文件进行安装,因为程序进入后台后还可以运行一段时间,所以这里是可行的。

可以使用第三方库CocoaHTTPServer在app端运行一个服务器。safari中访问 loacalhost:端口号/目录即可打开文件。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 - (void)startServer {      // Create server using our custom MyHTTPServer class      _httpServer = [[RoutingHTTPServer alloc] init];      // Tell the server to broadcast its presence via Bonjour.      // This allows browsers such as Safari to automatically discover our service.      [_httpServer setType:@ "_http._tcp." ];      // Normally there's no need to run our server on any specific port.      // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime.      // However, for easy testing you may want force a certain port so you can just hit the refresh button.      [_httpServer setPort:12345];      NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];      [_httpServer setDocumentRoot:documentsDirectory];      if  (_httpServer.isRunning) [_httpServer stop];      NSError *error;      if ([_httpServer start:&error])      {          NSLog(@ "Started HTTP Server on port %hu" , [_httpServer listeningPort]);      }      else      {          NSLog(@ "Error starting HTTP Server: %@" , error);          // Probably should add an escape - but in practice never loops more than twice (bug filed on GitHub https://github.com/robbiehanson/CocoaHTTPServer/issues/88)          [self startServer];      } } - (void)applicationDidEnterBackground:(UIApplication *)application {      // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.      // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.      backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{          [application endBackgroundTask:backgroundTask];          backgroundTask = UIBackgroundTaskInvalid;      }]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {      // Override point for customization after application launch.      [self startServer];      return  YES; }

safari中打开关键代码

1 2 3 4 5 __weak AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];      UInt16 port = appDelegate.httpServer.port;      NSLog(@ "%u" , port);      if  (success) [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@ "http://localhost:%u/profile.mobileconfig" , port]]];      else  NSLog(@ "Error generating profile" );

通过safari自带功能生成webclip

safari带有一个为当前网页生成webclip的功能,现在我们就需要使用这个方式来生成webclip。

这种方式的工作流程是这样的:先使用app打开safari并显示指定的网页内容(一般是指导用户怎么使用safari生成webclip,并打开safari的js控制),然后用户打开js权限,保存webclip,下次用户点击桌面上的webclip后即可再次打开该网页,触发js,跳回app。

因为用户点开webclip的时候需要获取到网页的所有信息,又因为我们的应用不是长时间在后台运行的,所以需要把所有网页的内容以url的形式中保存在webclip中,这种技术叫做data-url技术。

我们需要app把网页内容通过data-url的形式传给safari,我尝试过使用openurl的传输方式,这种方式不能传输太长的数据,行不通。所以这里的思路也是把app变成一个服务器,safari访问的时候返回302让TA重定向,重定向的url返回我们要传输的data-url,safari重定向后即可显示我们指定的网页内容。这里我们可以用基于CocoaHTTPServer之上封装的库RoutingHTTPServer。

  • 配置并传输data-url

1 2 3 4 5 6 7 8 9      //配置返回值      [appDelegate.httpServer get:@ "/old"  withBlock:^(RouteRequest *request, RouteResponse *response) {          [response setStatusCode:302];  // or 301          [response setHeader:@ "Location"  value:@ "data:text/html;charset=UTF-8," ];      }]; //跳转      UInt16 port = appDelegate.httpServer.port;      NSLog(@ "%u" , port);      [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@ "http://localhost:%u/old" , port]]];

用户打开js

《iOS保存app内容到手机桌面》

通过safari保存webclip

《iOS保存app内容到手机桌面》

  • data-url中加入js

通过safari打开的html是处于safari mode,而直接通过webclip打开的html是处于app mode,可以理解为safari mode是嵌入在safari中的网页,app mode的网页是单独的网页,通过这个状态我们可以控制什么时候调用js,来控制最终是展示当前网页还是跳转到我们指定的app。这里我写的是 sample:// ,可以按照需要替换成app的scheme,即可跳转到app。

1

其他可以做的细节

  • html和配置文件,我们都可以通过替换字符串等方式修改最终生成的内容,以此来针对不同用户生成不同内容。

1 2 3 4 5 6 7 NSString *templatePath = [[NSBundle mainBundle] pathForResource:@ "phone_template"  ofType:@ "mobileconfig" ];      NSString *data = [NSString stringWithContentsOfFile:templatePath encoding:NSUTF8StringEncoding error:NULL];      data = [data stringByReplacingOccurrencesOfString:@ "!!NAME!!"  withString:name];      data = [data stringByReplacingOccurrencesOfString:@ "!!PHONENUMBER!!"  withString:phoneNumber];      NSLog(@ "%@" , data);      BOOL success = [data writeToFile:[ProfileGenerator profilePath] atomically:YES encoding:NSUTF8StringEncoding error:nil];      return  success;
  • 端口号不一定要写死,这里仅仅是方便测试。

总结

2种方式都可以达到最终效果,选取哪种方式去实现,可以自己评估优劣。由于本人对服务端和前端不太熟悉,实现还有2点不足之处,希望有人能给出些比较好的方案。

可能由于浏览器缓存的问题,如果之前safari打开过localhost:端口号,下次再进入时可能不会去重定向,导致webclip保存的不是重定向后的url,而是原本请求的url。

重定向返回的response header长度这里也是有限制的,过长会造成截断,这里应该是可以通过代码改进的。


推荐阅读
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 《Axure新技能:自适应手机屏幕大小》相信不少人都已经看过,并对设置方法已经很熟悉了,但该教程只能适应iphone6的屏幕尺寸的比例&# ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • pyecharts 介绍
    一、pyecharts介绍ECharts,一个使用JavaScript实现的开源可视化库,可以流畅的运行在PC和移动设备上,兼容当前绝大部 ... [详细]
  • 今天凌晨开始苹果正式开始了iOS10的推送工作,使用iPhone和iPad的用户可 ... [详细]
  • iOS 12 beta8如何更新? iOS 12 beta8更新方法攻略介绍!
    iOS12beta8小伙伴们可以进行更新升级了,这次更新主要是为了解决之前出现的问题,不少小伙伴们比较好奇的就是该怎么更新,想知道更新方法的就一起来看看吧。更新方法介绍OS12兼容 ... [详细]
  • 前端提高篇(七十):SVG基本使用、基本样式、路径path
    SVG是使用XML来描述二维图形和绘图程序的语言。SVG遵循的是xml的规范,与html5的使用有所区别SVG绘制出来的是矢量图,放大之后不会失真官方文 ... [详细]
  • Scrapy 爬取图片
    1.创建Scrapy项目scrapystartprojectCrawlMeiziTuscrapygenspiderMeiziTuSpiderhttps:movie.douban.c ... [详细]
  • 目录爬虫06scrapy框架1.scrapy概述安装2.基本使用3.全栈数据的爬取4.五大核心组件对象5.适当提升scrapy爬取数据的效率6.请求传参爬虫06scrapy框架1. ... [详细]
  • 小程序引入外部文件的方式是:import**.wxss;因为业务需要,正在开发的小程序中需要使用iconfont,很容易想到了H5的引 ... [详细]
  • Python爬虫爬点大家喜欢的东西
    要说最美好的欲望莫过于看黑丝美眉。一、技术路线requests:网页请求BeautifulSoup:解析html网页re:正则表达式& ... [详细]
  • 一、Notification通知是属于桌面性质的通知,在显示器的右下角蹦出二、兼容性IE14以及其他桌面浏览器都支持WebNotification,目前 ... [详细]
  • 移动端Web开发的实用技巧与经验分享
    META相关1.添加到主屏后的标题(IOS)<metaname"apple-mobile-web-app-title& ... [详细]
author-avatar
罗斌强
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有