移动端Hybrid-iOS添加快捷方式到主屏幕

作者: DongLei | 来源:发表于2016-04-01 15:02 被阅读4047次

转载请注明出处

感谢三楼Wind_is_warm提的需求,针对Wind_is_warm的问题,程序增加了判断用户是否安装有目标APP的能力,如用户手机装有目标APP,点击桌面快捷图标,会直接跳转到应用,如用户未安装目标APP则会跳转到目标APP的下载页。

关于Hybrid研发模式,这里就不多说了,是目前移动端主流的研发模式。当我们的APP内部集成有很多Web实现的功能时,甚至某些Web实现的模块作为一部分独立的功能,打开的频率很高,这个时候,可以将对应的功能页面以快捷方式添加到桌面上。
如果Web功能与APP相对独立,可以通过此快捷方式直接代开Safari,用户可以在Safari中完成想要的操作。
另一方面如果Web功能的实现与APP高度耦合,或者出于增加APP的用户粘性角度,可以通过点击此快捷方式唤醒我们的APP并跳转到我们自己APP中的相应模块。

addBaiduToDesktop.gif

基本实现思想

利用Safari自带的添加到主屏幕功能,有两种实现方案,

实现方案一:

调用Safari访问外部页面,将外部页面作为快捷页面添加到桌面。
优点:实现简单,工作量少,页面灵活可随时更改。
缺点:无网状态下,无法生成快捷方式。

实现方案二:

通过应用内部启动httpServer,调用safari访问localhost,同时,在主页通过跳转到新的Data URI页面。
优点:不需要服务器,没网也能完成操作。
缺点:依赖的类库较多,而且实现较麻烦。

功能封装及技术实现

方案一比较简单,就不再多说了。
本文主要针对方案二,其中用到的一些知识包括HTML、cocoaHttpServer、Data URI Scheme等,关于Data URI Scheme相关知识,可以参考我的另一篇文章。
前端-Data URI Scheme:http://www.jianshu.com/p/ea49397fcd13

封装方法

针对方案二,对功能进行了封装,仅需调用3行代码,即可实现动态添加快捷方式到桌面。项目地址:https://github.com/dlgenius/DLAddToDesktop

DLAddToDesktopLib.gif

功能封装

用到的一些类库

  • CocoaHTTPServer
  • GTMBase64

使用方式:
1.工程中导入CocoaHTTPServer、GTMBase64类库
2.将Demo中的DLAddToDesktopLib文件夹拷贝到工程中

lib.png

3.在需要添加到主页面的按钮事件中加入如下代码,以下示例代码以跳转微信为例,如集成到自己的APP中,需将urlScheme和appDownloadUrl,需改为自己需要的参数。

DLAddToDesktopHandler *handler = [DLAddToDesktopHandler sharedInsance];
NSString *imageString = [[UIImage imageNamed:@"webIcon"] dataURISchemeImage];
[handler addToDesktopWithDataURISchemeImage:imageString
                                      title:@"Donglei"
                                  urlScheme:@"weixin://"
                             appDownloadUrl:@"https://appsto.re/cn/S8gTy.i"];

4.别忘记设置项目的URL Types

URL Schemes.jpg

下面是一些主要的方法,

/**
 *  @brief  创建DLCreateShortcutHandler单例
 *
 *  @return DLCreateShortcutHandler单例
 */

+(DLCreateShortcutHandler *)sharedInsance;

/**
 *  @brief  通过Safari添加快捷方式到桌面
 *
 *  @param  dataURISchemeImage   data URI scheme
 *  @param  title                快捷方式桌面名称
 *  @param  urlScheme            ios APP的URL Scheme
 *  @param  appDownloadUrl       应用下载地址
 *  @return void
 */
- (void)addToDesktopWithDataURISchemeImage:(NSString *)dataURISchemeImage title:(NSString *)title urlScheme:(NSString *)urlScheme appDownloadUrl:(NSString *)appDownloadUrl;


/**
 *  @brief  生成Data URL Scheme 形式的图片字符串
 *
 *  @return Data URL Scheme 形式的图片字符串
 */
- (NSString *)dataURISchemeImage;

技术实现

HTML 相关

苹果Safari本身支持网页添加到主屏幕功能,苹果官方文档参考,
https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

封装的库中,HTML头文件有如下代码

<head>
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta content="text/html charset=UTF-8" http-equiv="Content-Type" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>
    <link rel='apple-touch-icon' href='DLCSImageData'>
    <title>DLCSTitle</title>
</head>

其中,

  • apple-mobile-web-app-capable是用来定义应用全屏展示的。
  • apple-mobile-web-app-status-bar-style,在定义了。apple-mobile-web-app-capable的前提下,设置状态栏的属性值apple-mobile-web-app-status-bar-style才有效。
  • viewport,width用于指定宽度,initial-scale指定初始化的缩略比例,minimum-scale指定缩小的比例,而maximum-scale则是放大的比例,当然这些缩放都取决于user-scalable——决定用户是否能缩放页面。
  • rel='apple-touch-icon' href='DLCSImageData',添到主屏幕的图标,有两种属性值apple-touch-icon和apple-touch-icon-precomposed,区别就在于是否会应用iOS中自动给图标添加的那层高光。

另外,HTML中可以加入下面代码对添加到桌面的快捷方式设置启动页,使其更像一个APP,

<link rel="apple-touch-startup-image" sizes="2048x1496" href="">

但我们封装的代码中并没有加入此功能,
关于没有实现的原因,其实很简单,由于我们的技术实现方案是首先通过访问本地地址,然后跳到一个Data URI Scheme形式下的HTML页面,而添加到主屏幕的也是这个Data URI Scheme形式下的HTML页面,Data URI 是拼接在地址栏里的,图片数据经过Data URI形式编码处理,会生成一个很长的支付串,启动页图片一般都比较大,又经过了base64编码,加上我们添加到主屏幕的icon也经过了这样的处理,有可能会超出Safari对URL长度的限制,导致无法打开页面的问题,还有主要的原因就是data URI Scheme 移动端的性能很低,不适合内嵌大图。
但如果采用方案一,我们是通过访问外部页面来实现添加到主屏幕功能的,可以考虑实现此功能。

CocoaHTTPServer 相关

CocoaHTTPServer封装的很好,用起来也很简单

 //config HttpServer
    _myHTTPServer = [[HTTPServer alloc] init];
    [_myHTTPServer setType:@"_http._tcp."];
    [_myHTTPServer setPort:port];
    
    //setWebPath
    NSString *serverWebPath = [self getServerWebPath];
    BOOL created = [[NSFileManager defaultManager] createDirectoryAtPath:serverWebPath withIntermediateDirectories:YES attributes:nil error:nil];
    if(created){
        [_myHTTPServer setDocumentRoot:serverWebPath];
    }

通过以上代码我们就建立了一个本地服务器,然后调用start开启本地服务即可,

- (void)startServer{
    NSError *error;
    if([_myHTTPServer start:&error])
    {
        DDLogInfo(@"Started HTTP Server on port %hu", [_myHTTPServer listeningPort]);
    }
    else
    {
        DDLogError(@"Error starting HTTP Server: %@", error);
    }
}

业务逻辑实现相关

这里没有复杂的业务逻辑,主要是读取HTML文件、替换HTML文件中相应字段、存储HTML文件到HTTPServer的WebPath下,再通过Safar打开本地服务。大家可以去阅读我的源码。

项目地址

项目地址:https://github.com/dlgenius/DLAddToDesktop

Thanks

iOS中为网站添加图标到主屏幕以及增加启动画面 http://blog.csdn.net/lgd5979/article/details/7877998
...

相关文章

网友评论

  • LemonsCode:请问楼主,iOS升级12后,依旧会出现点击快捷方式,跳转到app又跳转到appstore的问题,怎么解决,谢谢:pray:
    DongLei:@Lemon的漫长岁月 程序的跳转逻辑是根据启动应用时差实现的,iOS12系统优化了应用启动速度, 程序已经针对iOS12进行优化修复,可下载最新代码进行参考,跳转APP和跳转APPStore逻辑在,content.html中的16至51行,也可自行优化。
  • cc76dfa4dad8:楼主 能加一下你的Q吗 请教一些问题谢谢
  • DongLei:感谢大家的点赞,关于iOS11兼容性问题,工程已经更新,包括:
    1、打开的网页为本地地址,本地服务器停止响应问题。
    2、手机本地已经按照了目标APP,但点击快捷图标时,跳转到目标APP后,依然会跳转APPStore下载地址的问题。
    最新代码,请到github进行下载:https://github.com/dlgenius/DLAddToDesktop
  • 754cc4a7ed6f:请问一下,如果我想从桌面快捷方式 回传参数给APP呢,该如何操作
    DongLei:在调用方法进行参数传递时urlScheme参数带着你需要回传的参数即可,参考:
    - (IBAction)addToDesktop:(id)sender {

    DLAddToDesktopHandler *handler = [DLAddToDesktopHandler sharedInsance];
    NSString *imageString = [[UIImage imageNamed:@"webIcon"] dataURISchemeImage];
    [handler addToDesktopWithDataURISchemeImage:imageString
    title:@"Donglei"
    urlScheme:@"DLAddToDesktop://para=a"
    appDownloadUrl:@"https://appsto.re/cn/S8gTy.i";];

    }
    同时在APPDelegate回调是使用回调函数获取你需要的回传参数:
    - (BOOL)application:(UIApplication *)application
    openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication
    annotation:(id)annotation {
    //参数url为回传的URL
    return YES;
    }
  • 梁森的简书:项目直接崩掉了
    第二个网址也是404
  • 414882c53e9a:改了自动分配端口和写死端口,也会出现第一次访问服务器不能响应问题,请问该怎么改进了?
    DongLei:@嗯嗯嗯嗯的时候 是的iOS11进入后台时,会导致搭建的服务器立即断开,加入如下代码即可
    - (void)applicationWillResignActive:(UIApplication *)application {
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

    }];
    }
    e6587d38ca0d:自己回答一下吧,找到原因如下,当调用openurl时,app执行applicationDidEnterBackground,进入后台,系统会让播放器停止,socket断开等,导致我们代码搭建的服务立即被断开,最终导致网页显示错误,解决方法就是在applicationDidEnterBackground方法中申请一个短暂的后台停留[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
    e6587d38ca0d:你好,请问你解决这个问题了吗
  • 小小溪001:本地服务建立不成功!怎么解决呢?
    e6587d38ca0d:自己回答一下吧,找到原因如下,当调用openurl时,app执行applicationDidEnterBackground,进入后台,系统会让播放器停止,socket断开等,导致我们代码搭建的服务立即被断开,最终导致网页显示错误,解决方法就是在applicationDidEnterBackground方法中申请一个短暂的后台停留[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
    e6587d38ca0d:你好,请问你解决这个问题了吗
  • 我打你吧:你好,我在真机上运行,加载HTML的时候,总是Safari打不开网页,服务器停止响应,但是返回再次生成快捷方式就可以,是为什么呢,谢谢
    e6587d38ca0d:你好,这个问题并没有解决呢,我没有修改demo中的任何代码,只要是safari进程被kill,第一次调起safari总是失败的,求解决
    我打你吧:@DongLei 谢谢
    DongLei:不好意思,公司内网限制,好久没看简书,
    您是否有对demo中,一下代码的localPort进行过修改,此问题应该是CocoaHTTPServer的使用问题,CocoaHTTPServer的本地服务建立不成功。

    [self addToDesktopWithDataURISchemeImage:dataURISchemeImage
    title:title
    urlScheme:urlScheme
    appDownloadUrl:appDownloadUrl
    localPort:1077];
  • 简教练:666666,这个我也是看其他app有这样的操作 没想到你这里已经弄出来了,非常感谢 :pray: :pray: :pray:
  • DongLei:感谢三楼Wind_is_warm提的需求,针对Wind_is_warm的问题,程序增加了判断用户是否安装有目标APP的能力,如用户手机装有目标APP,点击桌面快捷图标,会直接跳转到应用,如用户未安装目标APP则会跳转到目标APP的下载页。
    GitHub上的代码已经更新。
  • Wind_is_warm:写的不错,不过还是想请问如何实现类似百度地图的快捷方式:如果百度地图卸载,打开快捷方式会给出一个连接指引用户去AppStore下载百度地图?
    Wind_is_warm:@DongLei 多谢指导:smile:
    DongLei:@Wind_is_warm
    最近公司组织结构大调整,心好累,这段时间没分出精力关注博客。
    百度地图这种形式其实很简单,如果想跳转第三方应用,那么需要知道第三方应用的URLScheme,HTML页面a标签的href为AppStore下载地址,页面通过iframe的方式尝试打开APP,如用户安装有应用,会直接切换到APP,并进行跳转,这时会自动阻止a标签的默认行为。如用户未安装,直接走a标签的默认行为,
    下面是我改写的一部分代码,供参考,后面会抽时间整理到博客和demo中
    <body>
    <a href="注意这块要替换成AppStore的应用地址" id="qbt" onclick="autoJump()"></a>

    <div style="margin-left: 15px; margin-top: 150px"> <span id="msg"></span></div>
    </body>
    <script>
    if (window.navigator.standalone == true)
    {

    function autoJump(){
    // 通过iframe的方式试图打开APP,如果能正常打开,会直接切换到APP,并自动阻止a标签的默认行为
    // 否则打开a标签的href链接
    var ifr = document.createElement('iframe');
    ifr.src = 'DLAddToDesktop://';
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
    window.setTimeout(function(){
    document.body.removeChild(ifr);
    },3000)
    };

    document.getElementById("qbt").click();

    }
  • 22becf5aab42:哇塞,这个太有用了,作者好赞!!!

本文标题:移动端Hybrid-iOS添加快捷方式到主屏幕

本文链接:https://www.haomeiwen.com/subject/dyhylttx.html