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文件夹,文件夹内容应该如下:
(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)运行程序,“进入小明的直播间”
网友评论