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

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

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

safari生成webclip

这种效果就是苹果的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

通过safari保存webclip

  • data-url中加入js

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

1
<br>

其他可以做的细节

  • 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保存app内容到手机桌面相关推荐

  1. ios 收藏app内容或网页到手机桌面

    最近看了一篇<保存app内容到手机桌面>感觉挺不错,于是自己参照着也做了一个demo.在此主要记录一些编写demo中遇到的问题. 先感谢下<保存app内容到手机桌面>的原作者, ...

  2. android 开机直接运行app并当做手机桌面

    android 开机直接运行app并当做手机桌面 直接上代码: 1.开机启动APP 1.1 写一个广播接收器,用来接收手机开机广播 public class Receiver extends Broa ...

  3. Android app图标在手机桌面显示过小

    开发中,app安装在手机之后,图标明显比其他app的图标要小,开始认为与手机设备有关,后经检查后发现与手机分辨率有关,出问题的为三星手机1080p,Android会根据手机分辨率自动到相应的文件夹下( ...

  4. 有没有一种手机桌面便签记事本可以把日常安排写在上面并提醒自己

    手机便签记事本一般都具备文字记事的功能,一些好用的手机便签记事本还能设置将便签记事内容直接显示在桌面上,以便时时查看提醒自己.那么有没有一种手机桌面便签记事本可以把日常安排写在上面并提醒自己的呢? 其 ...

  5. 手机桌面记事本在哪里设置

    手机记事本是我们在很多场景下都会使用的记事工具,例如随手记录读书笔记.观赏风景的感悟.工作注意事项.客户的联系方式.待办的各种任务等.此外为了更加便捷记事.起到更好的备忘或提醒作用,有些记事本APP还 ...

  6. 挑战微信、试探苹果?支付宝小程序可添加到 iOS 手机桌面

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! [CSDN编者按]从微信小程序到快应用,移动互联网正面临着一场重新洗牌.以往的应用分发模式已 ...

  7. iOS新闻类App内容页技术探索

    为了更好的阅读体验,建议阅读原文 据相关数据显示,截至2017年底,中国手机新闻客户端用户规模达到6.36亿人,移动App已经成为新闻和内容传播的最重要途径之一.而伴随着行业的竞争和发展,App中的内 ...

  8. 安卓桌面整理app_【小编分享】APP整理大法!跟杂乱无章的手机桌面说拜拜~

    原标题:[小编分享]APP整理大法!跟杂乱无章的手机桌面说拜拜~ 现在的手机应用市场上面每天都有数以万计的APP"新货"上架,又有众多应用软件被淘汰,而从来不缺的就是标签明显.紧跟 ...

  9. 如何把一个网页设置快捷方式放到桌面上去,或者手机桌面当App一样使用

    分别讲电脑端和手机端: 电脑端: 在尝试好几种方式后,还是觉得最最简单的方法,还是用电脑自带的方式不借助任何外力方便,利用谷歌的方式也讲一下哈(利用谷歌会有自己的图标这点不错); 其他方式: http ...

最新文章

  1. 消灭 Java 代码的“坏味道”
  2. 用Visual C#做DLL文件
  3. [转帖]爬过这 6 个坡,你就能对 Linux 操作系统了如指掌
  4. Spring中IoC的入门实例
  5. tableau实战系列(八)-用数据桶实现图表的固定轴距
  6. 三维数据平滑处理_你该如何正确的处理思看科技三维扫描仪得到的数据?
  7. :focus-within的冒泡触发
  8. market1501正则表达式提取行人id和相机id
  9. android谷歌打印插件下载地址,ARC Welder(App Runtime for Chrome)插件下载 附下载地址
  10. bzoj 4956: [Wf2017]Secret Chamber at Mount Rushmore(最短路)
  11. java操作JSON对象
  12. Calendar类方法——编写万年历的两种方式
  13. 高德地图接口申请 地图接口集成 高德地图API文档
  14. 电脑上m4a怎么转换成mp3
  15. matlab 简单算例,(简单算例)基于Matlab的电力系统潮流编程计算.pdf
  16. 企业微信小程序获取手机号?
  17. 最近对物联网文章读后感
  18. 如何更方便的探讨技术
  19. 微型计算机室内太干燥,暖气屋里太干燥怎么办 七种方法增加室内湿度
  20. maven中archetype(原型)的使用及创建

热门文章

  1. OpenStack安装教程
  2. 怎么理解c语言,到底怎么样C语言才算入门?大一新生的痛:这些你理解了多少...
  3. excel想把B列、C列的内容插入到A列里面怎么操作
  4. 千元内面单吉他推荐,VEAZEN费森VZ200和enya恩雅X1pro评测对比哪款更出众?
  5. 韩国牛奶进口税率及进口牛奶那些流程事项2021-08-19
  6. 《喝彩中华》:奥运冠军杨景辉跨界结缘豫剧
  7. IDEA编译项目提示程序包不存在、符号错误,最终幻想
  8. Vue2中过滤器的用法详解
  9. 测试人生 | (汇总篇)从小团队的业务到独角兽的测开,涨薪超过60%,90后小哥哥凤凰涅槃了
  10. 新手开始玩ubuntu