ios 关于支付宝添加桌面快捷方式的探究

前言

最近公司产品有个需求,为我们app中每个H5应用实现添加桌面快捷方式的功能,与支付宝健康码添加到桌面一样。所以特地研究了下相关产品中该功能的实现方式,如哈罗单车和支付宝。

原理

在 app 里面通过 OpenURL 方式 跳转到Safari 浏览器,打开一个引导页面,然后点击添加到主屏幕,如下图:

1241595556274_.pic.jpg

哈罗单车的实现

548341-fb5e56e2ad03a85a.png

哈罗单车在Safari中展示的是一整张引导图片,为啥这里说一整张图呢,因为支付宝展示的引导页是由多张图片拼接而成。

哈罗单车不同的业务使用快捷方式,需要UI每次做一张引导图,或者做一张通用图片当引导图。

探索支付宝添加桌面快捷方式的实现

  1. 在关闭网络的情况下,在支付宝健康码中点击"添加到桌面",跳转到Safari浏览器,得到url

https://render.alipay.com/p/s/shortcut/index?appId=20000067&appName=杭州健康码&appIcon=https://gw.alicdn.com/tfs/TB1nUmbzUT1gK0jSZFhXXaAtVXa-1024-1024.png&appUrl=https%3A%2F%2Fh5.dingtalk.com%2FhealthAct%2Findex.html

可以看出url为https://render.alipay.com/p/s/shortcut/index,后面参数有appId,appName,appIcon,appUrl

  1. 支付宝小程序也同样有添加到桌面的功能,同样的方式获取到小程序跳转到Safari浏览器中的url,这里以"体育服务"小程序为例

https://render.alipay.com/p/s/shortcut/index?appId=2018073060792690&appName=体育服务&appIcon=https://appstoreisvpic.alipayobjects.com/prod/[email protected]

  1. 我们将支付宝健康码页面的url在mac上的Safari 浏览器打开,查看元素


    截屏2020-07-23 下午6.49.10.png

可以看到页面主要有index.html,index.js,还有几张图片


截屏2020-07-23 下午6.54.49.png

从这张图我们可以猜到,支付宝是通过html和js将appIcon动态嵌入到上图相应的位置,以此来实现safari中的引导页面。

比较

支付宝的实现方式更加高明,采用动态拼接图片的方式,业务方只需要传入appIcon。

但是哈罗单车主要是靠app客户端实现的,支付宝则是靠Web端来实现。

支付宝总体实现

通过对index.html和index.js的分析,得出支付宝实现方式如下:

app客户端请求站点https://render.alipay.com/p/s/shortcut/index,并将appId,appName,appIcon,appUrl等传递过去。站点下index.html中接收url中携带的参数值,生成对应的base64。

这样app客户端实现起来很简单,只需要打开url并将参数传递过去即可。剩下的交由Web端开发来做。

   //支付宝实现应用桌面快捷方式
   //url中不含中文时,可以不对url进行unicode转码,使用https://render.alipay.com/p/s/shortcut/index?appId=20000067&appName=123&appIcon=https://gw.alicdn.com/tfs/TB1nUmbzUT1gK0jSZFhXXaAtVXa-1024-1024.png&appUrl=https://Fh5.dingtalk.com/FhealthAct/Findex.html也可以
   NSURL *URL = [NSURL URLWithString:@"https://render.alipay.com/p/s/shortcut/index?appId=20000067&appName=123&appIcon=https://gw.alicdn.com/tfs/TB1nUmbzUT1gK0jSZFhXXaAtVXa-1024-1024.png&appUrl=https%3A%2F%2Fh5.dingtalk.com%2FhealthAct%2Findex.html"];
    
   UIApplication *application = [UIApplication sharedApplication];
   NSURL *URL = [NSURL URLWithString:urlString];

   if (@available(iOS 10.0, *)) {
       [application openURL:URL options:@{}
           completionHandler:^(BOOL success) {
       }];
   } else {
       [application openURL:URL];
   }

但是我身为一个ios开发,可不可以不借助Web端开发,自己单独来实现呢?
如果自己单独实现,需要解决哪些问题呢?

  1. 首先我从mac端浏览器中可以获取到index.html和index.js和图片等资源文件
  2. 我们需要将支付宝的index.html文件中原本通过url中获取参数的形式改为app本地替换

步骤

1. 开发引导页面

我们首先在app项目工程的根目录下创建一个文件夹Web,文件夹下存放引导页面


截屏2020-07-23 下午7.44.32.png

content.html

content.html是拷贝的是支付宝index.html文件,对其做了修改。

  1. 支付宝的index.html文件通过从浏览器的url中获取参数,通过js函数getQueryParams实现。因为我的参数没有放在URL中,所以通过getQueryParams函数获取到的参数都是空的。可以给appId等参数赋个默认值,这样就实现了本地参数替换。

var query = getQueryParams(location.href);
var { appId = "TransitCodeAppId", appName= "TransitCodeAppTitle", appIcon = "TransitCodeAppIcon", appUrl = "ezvizsaas://123", scheme = "TransitCodeAppScheme" } = query;

修改过后的content.html代码如下:

将其中的"企业萤石云"改成自己的主app名称即可,也可使用字符串进行动态替换。



  
    
    企业萤石云
    
    
    
    
    
    
    
    
  
  
    
    
    

  
  
      




  

代码中包含的一些字符串含义如下:
TransitCodeAppIcon:快捷方式在桌面的图标
TransitCodeAppTitle:快捷方式的名称
TransitCodeAppScheme:跳转页面对应的 scheme,比如 ezvizsaas://web/app?appId=1

通过这几个字符串代替实际内容,就可以做到动态替换。"企业萤石云"替换为自己的主app名称即可。

这里通过 window.navigator.standalone 可以知道引导页是否是全屏展示,如果是全屏那么跳转到 app 对应页面,非全屏则插入具体 HTML 内容,展示引导内容。

index.js

index.js中代码过长,由于对内容长度的限制,会导致无法发布,这里就不贴出来了。

index.js用的是支付宝的代码,其中许多代码是无用的,不过不影响我们的业务,可以不用删减。js中的一些关于"支付宝"的文本可以替换成我们的。

2. 使用 Data URI Scheme 技术将引导页转为一个字符串

代码如下

//iconUrl:桌面图标 appTitle:默认app名称
- (NSString *)oppcreateDesktopWithPreUrl:(NSString *)preUrl iconUrl:(NSString *)iconUrl appTitle:(NSString *)title scheme:(NSString *)scheme {
    if ([preUrl length] == 0) {
        return nil;
    }
    NSString *contentHtmlString = [self contentHtmlWithIconImageString:iconUrl title:title appScheme:scheme];
    NSData *data = [contentHtmlString dataUsingEncoding:NSUTF8StringEncoding];
    contentHtmlString = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; // base64格式的字符串;
    NSString *DataURIString = [NSString stringWithFormat:@"data:text/html;charset=utf-8;base64,%@",contentHtmlString];
    NSString *urlString = [NSString stringWithFormat:@"%@%@", preUrl, DataURIString];
    return urlString;
}

-(NSString *)contentHtmlWithIconImageString:(NSString *)iconImageString title:(NSString *)title appScheme:(NSString *)scheme{
    NSString *contentHtmlPath = [self getcontentHTMLTempletPath];
    NSString *contentHtmlString = [NSString stringWithContentsOfFile:contentHtmlPath encoding:NSUTF8StringEncoding error:nil];
    /*替换字符串*/
    contentHtmlString = [contentHtmlString stringByReplacingOccurrencesOfString:@"TransitCodeAppIcon" withString:iconImageString];
    contentHtmlString = [contentHtmlString stringByReplacingOccurrencesOfString:@"TransitCodeAppTitle" withString:title];
    contentHtmlString = [contentHtmlString stringByReplacingOccurrencesOfString:@"TransitCodeAppScheme" withString:scheme];
    return contentHtmlString;
}

- (NSString *)getcontentHTMLTempletPath{
    NSString * path = [[NSBundle mainBundle] pathForResource:@"content" ofType:@"html"];
    return path;
}

Data URI Scheme 技术就是将一个文件,图片或者HTML文件等等,通过 Base64 加密等转为字符串放到 HTML 里面直接加载,这样就不用请求服务器了。这里我们需要将上面介绍的本地的引导 HTML 页面转为一个字符串,后面要将这个字符串拼到服务器HTML url 后面。

看代码可以知道,通过 getcontentHTMLTempletPath 方法拿到本地 HTML 文件路径,然后将里面内容进行替换为我们应用的快捷方式相关内容。然后将 HTML 内容转为 base64 编码。最后通过将 base64 编码按照特定格式拼接即可,这里是
[NSString stringWithFormat:@"data:text/html;charset=utf-8;base64,%@",contentHtmlString];以 data:text/html;charset=utf-8;base64, 开头,后面我们可以看到存储的时候也是保存的这个。

3. 打开服务器 HTML 页,用本地引导页替换

用上面生成的字符串拼到服务器 HTML 页面url (这里我是直接将 HTML 文件发给Web端同事,放到 Web网站上面然后拿到链接)后面,代码如下

//下面是添加快捷方式到桌面的相关代码
- (void)addShortcutToDesk {
    NSString *baseUrl = @"https://www.baidu.com";  //这里将https://www.baidu.com替换为你自己的shortcut-middle.html所在的Web服务器地址
    NSString *preUrl = [NSString stringWithFormat:@"%@/shortcut-middle.html",baseUrl];
    preUrl = [NSString stringWithFormat:@"%@?dataurl=", preUrl];
    NSString *title = [self.webAppParams objectForKey:@"appName"];
    NSString *scheme = [NSString stringWithFormat:@"ezvizsaas://web/app?appId=%ld",self.webAppId];
    NSString *iconUrl = [self.webAppParams objectForKey:@"appLogo"];
    NSString *urlString = [self oppcreateDesktopWithPreUrl:preUrl iconUrl:iconUrl appTitle:title scheme:scheme];
    UIApplication *application = [UIApplication sharedApplication];
    NSURL *URL = [NSURL URLWithString:urlString];

    if (@available(iOS 10.0, *)) {
        [application openURL:URL options:@{}
           completionHandler:^(BOOL success) {
        }];
    } else {
        [application openURL:URL];
    }
}

这里服务器保存的 HTML页面shortcut-middle.html很简单,加载后主要就是通过上面拼接的链接获取本地引导页内容,然后加载引导页,shortcut-middle.html代码如下




    





通过 location.search 方法可以获取到拼接好的url内容,然后拿到我们拼上去的内容,使用 window.location.replace 方法来重新进行内容替换,就可以展示我们本地的引导页了。此时展示就是非全屏展示,跟从快捷键打开不一样。

可能遇到的问题

  1. 在Safari中出现如下错误提示 414 Request-URI Too Large

这是因为我们的url超过了nginx 服务器的限制,找Web端开发人员设置下nginx 服务器的配置即可。
参考https://blog.csdn.net/qq_41198398/article/details/83618204

  1. 添加到桌面的图标有黑边
    这是因为我们传入的appIcon图标有圆角,appIcon用大图512x512或1024x1024,不要圆角

参考资料

  1. 哈罗单车乘车码添加桌面快捷方式
    https://www.jianshu.com/p/15e36a3bd22c
  2. 支付宝健康码和小程序添加桌面快捷方式

你可能感兴趣的:(ios 关于支付宝添加桌面快捷方式的探究)