美文网首页
sirikit shortcuts

sirikit shortcuts

作者: Alienchang | 来源:发表于2018-12-24 19:37 被阅读11次

    shortcuts只支持 iOS12+,而且功能也不是很强大,但是从设计思路层面看还是会往更智能开放的方面走。

    下面我要做关于sirikit的三个小功能,shortcuts会放在第三个,但是这三个小功能也是目前sirikit所支持的一切,
    分别是给某人发送消息,付款、shortcuts 的自定义事件

    开始准备工作

    (1)所有的前提是工程需要支持siri,所以登录开发者账号,找到目标AppId,编辑,然后打开以下两个权限:


    Screen Shot 2018-12-24 at 7.38.45 PM.png

    App Groups 是保证extension中的数据和主程序中的数据互通。

    Screen Shot 2018-12-24 at 7.38.54 PM.png

    继续在开发者中心新建一个App Group,格式为group.xxxxx.extension,随心而定。

    在主工程的info.plist中添加Privacy - Siri Usage Description,跟麦克风等其它功能一样,提示用户需要siri权限

    (2)回到Xcode,新建一个siri的extension,就叫TestSiriService(步骤如下):


    Screen Shot 2018-12-24 at 7.26.12 PM.png
    Screen Shot 2018-12-24 at 7.26.24 PM.png

    点击next按钮后生成SiriService文件夹,文件夹内容应该如下:

    Screen Shot 2018-12-24 at 7.31.11 PM.png
    (3)选中工程的target->Capabilities,打开下面的Siri tab和App Groups,AppGroup选择你自己刚才创建的GroupId。
    Screen Shot 2018-12-24 at 7.35.28 PM.png
    切换到SiriService target->Capabilities,同样打开App Groups,并选择你自己刚才创建的GroupId。这样主工程和extension都在一个group中,数据才可以互通。

    一、使用siri发消息

    (1)在siriService中的info.plist中添加如下图的字段,功能是类似全选,告诉app要使用发送消息的功能,这个是sirikit自带的默认字段


    Screen Shot 2018-12-24 at 8.02.27 PM.png

    (2)建立SiriTool文件,target勾选主工程和extension,保证两个位置都能使用,这个类我用于实现siriService功能的工具类

    SiriTool.h
    @interface SiriTool : NSObject
    + (void)sendMessage:(NSString *)message;
    @end
    
    + (void)sendMessage:(NSString *)message {
        // 这个位置一定要用initWithSuiteName,这个方法与stand的区别就是可以在不同target相同的group中互通数据,如果使用stand,数据是不会互通的
        //  suiteName一定要是你自己申请的GroupID
        NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxxxxx.extension"];
        [userDefault setValue:message forKey:@"message"];
        [userDefault synchronize];
    }
    

    (3)在ViewController中添加显示message的label:

    [self.messageLabel setText:[SiriTool message]];
    

    (4)在extension中新建SendMessageIntentHandler

    SendMessageIntentHandler.h
    #import <Foundation/Foundation.h>
    #import <Intents/Intents.h>
    NS_ASSUME_NONNULL_BEGIN
    
    @interface SendMessageIntentHandler : INExtension
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    SendMessageIntentHandler.m
    #import "SendMessageIntentHandler.h"
    #import "ViewController.h"
    #import "SiriTool.h"
    #import <Intents/Intents.h>
    @interface SendMessageIntentHandler()<INSendMessageIntentHandling>
    
    @end
    @implementation SendMessageIntentHandler
    // 用于解析处理接收到的数据
    - (void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent completion:(void (^)(NSArray<INSendMessageRecipientResolutionResult *> * _Nonnull))completion {
        NSArray<INPerson *> *recipients = intent.recipients;
    
        if (recipients.count == 0) {
            completion(@[[INSendMessageRecipientResolutionResult needsValue]]);
            return;
        }
        NSMutableArray<INSendMessageRecipientResolutionResult *> *resolutionResults = [NSMutableArray array];
        for (INPerson *recipient in recipients) {
            NSString *recipientName = recipient.displayName;
            if ([recipientName isEqualToString:@"小明"]) {
                [resolutionResults addObject:[INSendMessageRecipientResolutionResult successWithResolvedPerson:recipient]];
                completion(resolutionResults);
                return;
            }
        }
        
        [resolutionResults addObject:[INSendMessageRecipientResolutionResult unsupported]];
        completion(resolutionResults);
    }
    // 用于确认动作
    - (void)confirmSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {
        [SiriTool sendMessage:intent.content];
        NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
        INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeReady userActivity:userActivity];
        completion(response);
    }
    // 发送或者取消发送回执
    - (void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {
        
        NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
        INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
        completion(response);
    }
    @end
    

    (5)打开siri extension中自带的IntentHandler类,这个类的功能是处理siri听到声音的回调,为了不使这个类因为功能增加而变得复杂,我把这部分处理功能分发给SendMessageIntentHandler。如下:

    - (id)handlerForIntent:(INIntent *)intent {
        if ([intent isKindOfClass:[INSendMessageIntent class]]) {
            return [SendMessageIntentHandler new];
        }
        return nil;
    }
    

    (6)开始测试,先正常跑一边程序,以授权siri功能,然后scheme选中SiriService,目标选择siri,run:


    Screen Shot 2018-12-24 at 8.18.57 PM.png

    (7)我的工程名,也就是display是"哈哈",我需要跟siri说,“使用哈哈发消息”,“给小明发”,“发送250”,这样发送成功后重新打开程序刷新消息,应该就会出现250

    二、使用siri支付

    三、自定义命令(shortcuts)

    (1)在主工程中新建siriKit Intent file


    custom Intent 中有一个Category,这里有很多动作,但是现在好像没什么用,估计以后会做成根据语音自动识别吧。


    (2)在Intent file中新建Intent,命名为EnterRoom,并新建一个参数,叫name,这个是一个变量,你可以在程序中去设置它:
    image.png
    (3)之后这个intent会根据你所选的选项,在指定的target中动态生成类,类名为EnterRoomIntent.h这样子:
    image.png
    根据需要,勾选在哪个target中自动生成,或者干脆不勾选target
    (4)新建EnterRoomIntentHandler,与上面的handle功能一样,处理自定义事件逻辑
    @interface EnterRoomIntentHandler : INExtension
    
    @end
    
    #import "EnterRoomIntentHandler.h"
    #import "EnterRoomIntent.h"
    #import "SiriTool.h"
    @interface EnterRoomIntentHandler()<EnterRoomIntentHandling>
    @end
    @implementation EnterRoomIntentHandler
    - (void)handleEnterRoom:(EnterRoomIntent *)intent completion:(void (^)(EnterRoomIntentResponse *response))completion NS_SWIFT_NAME(handle(intent:completion:)) {
        [SiriTool setRoomName:intent.name[0]];
        NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([EnterRoomIntent class])];
        EnterRoomIntentResponse *response = [[EnterRoomIntentResponse alloc] initWithCode:EnterRoomIntentResponseCodeSuccess userActivity:userActivity];
        completion(response);
    }
    @end
    

    (5)在ViewController中添加快捷添加语音唤起功能,iOS12中新添加了一个siri Button,为了添加自定义语音。这个自定义语音随便定义,我的是,“进入小明的直播间”

    INUIAddVoiceShortcutButton *siriButton = [[INUIAddVoiceShortcutButton alloc] initWithStyle:INUIAddVoiceShortcutButtonStyleBlack];
    [siriButton setFrame:CGRectMake(50, 250, 130, 40)];
    [self.view addSubview:siriButton];
    [siriButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
    
    - (void)buttonAction {
        if (@available(iOS 12.0, *)) {
            EnterRoomIntent *intent = [EnterRoomIntent new];
            // 这个name就是intent file中的name变量,可以在EnterRoomIntentHandler中获取
            [intent setName:@"小明"];
            INShortcut *shortcut = [[INShortcut alloc] initWithIntent:intent];
            INUIAddVoiceShortcutViewController *viewController = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortcut];
            [viewController setModalPresentationStyle:UIModalPresentationFormSheet];
            [viewController setDelegate:self];
            [self presentViewController:viewController animated:YES completion:nil];
        } else {
            // Fallback on earlier versions
        }
    }
    

    (6)运行程序,“进入小明的直播间”

    demo: https://github.com/Alienchang/SiriKit-shortcuts-demo

    相关文章

      网友评论

          本文标题:sirikit shortcuts

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