INSendMessageIntentHandling sirkit skipping handleSendMessage intent - ios

I added NSLog(..) statements on each method but it was not going to the handle send message delegate. I need to get some message from Siri to do some tasks. Also, is there any way to get the date/time from speech with INSentMessageDomiain
import "IntentHandler.h"
// As an example, this class is set up to handle Message intents.
// You will want to replace this or add other intents as appropriate.
// The intents you wish to handle must be declared in the extension's Info.plist.
// You can test your example integration by saying things to Siri like:
// "Send a message using <myApp>"
// "<myApp> John saying hello"
// "Search for messages in <myApp>"
#interface IntentHandler () <INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling>
{
NSString *resName;
}
#end
#implementation IntentHandler
- (id)handlerForIntent:(INIntent *)intent {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
if ([intent isKindOfClass:[INSendMessageIntent class]]) {
}
return self;
}
#pragma mark - INSendMessageIntentHandling
// Implement resolution methods to provide additional information about your intent (optional).
- (void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion {
// If no recipients were provided we'll need to prompt for a value.
NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
//NSArray<INPerson *> *recipients = intent.recipients;
[resolutionResults addObject:[INPersonResolutionResult notRequired]];
completion(resolutionResults);
}
- (void)resolveContentForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(INStringResolutionResult *resolutionResult))completion {
NSString *text = intent.content;
if (text.length == 0) {
completion([INStringResolutionResult needsValue]);
}
else {
completion([INStringResolutionResult successWithResolvedString:text]);
}
}
// Handle the completed intent (required).
- (void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse *response))completion {
//Implement your application logic to send a message here.
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc]initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
completion(response);
}

Related

Google unified messaging platform SDK implementation

I am wondering how I can make the form show in my iOS App https://developers.google.com/admob/ump/ios/quick-start.
I am using Xcode vs 11.6 and exported the game from Godot game engine.
I have changed the GADApplicationIdentifier in my info.plist and I don't get any errors in my code it just doesn't show the form when I run the game. I live in Europe. Any help is appreciated.
This is my current code:
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
- (void)viewDidLoad {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
[super viewDidLoad];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
}
}
}];
}
#end
EDIT
Add a few NSLog to see what gets called.
try the following - just a stone into the bush, maybe it hits something ...
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
// Change this one
- (void)viewDidLoad {
[super viewDidLoad];
}
// Add this one
- ( void ) viewDidAppear:( BOOL ) animated {
[super viewDidAppear:animated];
// View controller is now visible and on screen, so request permission
self.addMobStuff;
}
// Change / add this one
- ( void ) addMobStuff {
NSLog( #"addMobStuff" );
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
if ( ! UMPConsentInformation.sharedInstance )
{
NSLog(#"No shared instance");
}
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
NSLog(#"Some error %#", error);
} else {
NSLog(#"Proceed to form ...");
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
NSLog(#"Loading form ...");
[self loadForm];
}
else {
NSLog(#"Form status is not available");
}
}
}];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
NSLog(#"Form error %#", error);
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
NSLog(#"Presenting form");
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
NSLog(#"Changes");
}
}
}];
}
#end
note if this works it probably needs a bit more polish before it can be released into the world but hopefully at least the request form will be displayed ...

CXProviderDelegate Methods not called

My goal is to open my CallViewController after the user answers the call. I've read some excerpts here on SO that it can be done using:
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
NSLog(#"performAnswerCallAction");
}
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
NSLog(#"performStartCallAction");
}
The code above is inside AppDelegate.
However, using NSLogs, these methods aren't triggered at all. I can't seem to find any tutorials on implementing using Objective-C that is easy to understand from a beginner's POV. I would appreciate any insights, thanks!
First of all, did you set the delegate of CXProvider?
let provider = CXProvider(configuration: your_call_kit_config)
provider.setDelegate(self, queue: nil) // 'nil' means it will run on main queue
Also, have the AppDelegate.swift file conform to CXProviderDelegate
provider:performAnswerCallAction: gets called when user taps on 'Answer' button on the incoming call screen provided by the system. (Apple documentation HERE).
provider:performStartCallAction: gets called after successful request to CXCallController to perform a CXStartCallAction (Apple documentation HERE).
EDIT: For Objective-C
Ok here is the Objective-C snippet, for example, in the AppDelegate. First, you need to make AppDelegate conform to the CXProviderDelegate, Like so:
#interface AppDelegate () <CXProviderDelegate>
Then, add a property for CXProvider and CXCallController, like so:
#interface AppDelegate () <CXProviderDelegate>
#property (nonatomic, nonnull, strong) CXProvider *provider;
#property (nonatomic, nonnull, strong) CXCallController *callController;
#end
In the AppDelegate's function application:willFinishLaunchingWithOptions:, initialize CXProvider object with the call configuration, like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Setup CallKit
CXProviderConfiguration *providerConfiguration = [[CXProviderConfiguration alloc] initWithLocalizedName:#"MyApp"];
providerConfiguration.supportsVideo = YES;
providerConfiguration.includesCallsInRecents = YES;
self.provider = [[CXProvider alloc] initWithConfiguration: providerConfiguration];
// Since `AppDelegate` conforms to `CXProviderDelegate`, set it to the provider object
// Setting 'nil' to `queue` argument means, that the methods will be executed on main thread.
// Optionally, you can assign private serial queue to handle `CXProvider` method responses
[self.provider setDelegate:self queue:nil];
// Initialize `CallController`
self.callController = [[CXCallController alloc] init];
return YES;
}
And on the bottom of AppDelegate.m file, implement CXProviderDelegate methods:
#pragma mark: - CXProvider delegate methods
- (void)providerDidReset:(CXProvider *)provider {
// Drop all calls here (if there are pending)
}
/*!
This method gets called when user presses on 'Accept' button on the incoming call screen provided by the system.
Here you should configure `AVAudioSession` for VoIP calls and handle logic for answering the call.
*/
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
// Put your answering logic here
// Note: It is important to fulfill the action inside the scope of it's function, or to fail, depending if error occured during answering
[action fulfill];
}
/*!
This method gets called when CXCallController object finishes the CXStartCallAction request. You need to request
start call action to the CXCallController instance, when starting an outgoing VoIP call. After successful transaction,
the provider will respond with this delegate method. Here you should also configure `AVAudioSession` for VoIP calls.
*/
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
// Put your outgoing call action here
// Note: It is important to fulfill the action inside the scope of it's function, or to fail, depending if error occured during starting a call
[action fulfill];
}
To start an outgoing VoIP call, you need to request the transaction with the action to the CXCallController instance, like so:
#pragma mark - Call Controller requests
- (void)startOutgoingVoIPCallWithNumber:(NSString *)number {
NSUUID *callUUID = [NSUUID UUID]; // Here you create or assign UUID of call.
CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:number];
CXStartCallAction *startCallAction = [[CXStartCallAction alloc] initWithCallUUID:callUUID handle:callHandle];
startCallAction.video = YES; // Yes or no is call is video or audio.
CXTransaction *startCallTransaction = [[CXTransaction alloc] initWithAction:startCallAction];
[self.callController requestTransaction:startCallTransaction completion:^(NSError * _Nullable error) {
if (error) {
// Handle start call error here
// Ususally, error occurs if the system cannot handle the new outgoing call, since there are others pending
}
// If there is no error, CXProvider will respond with `provider:performStartCallAction:` method.
}];
}
To display system call screen
#pragma mark - Report New incoming call
/*!
You need to call this function each time you receive a new incoming call, usually right from the VoIP push notification.
*/
- (void)reportNewIncomingCallWithNumber:(NSString *)number {
NSUUID *callUUID = [NSUUID UUID]; // Call UUID, you should have this in some Call object, not generating the new here
CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:number];
CXCallUpdate *callInfo = [[CXCallUpdate alloc] init];
callInfo.remoteHandle = callHandle;
[self.provider reportNewIncomingCallWithUUID:[NSUUID UUID] update:callInfo completion:^(NSError * _Nullable error) {
if (error) {
// Handle error here
}
// If there is no error, system will display incoming call screen and when user taps on 'Answer',
// `CXProvider` will respond with `provider:performAnswerCallAction:`
}];
}
Just in case anyone's coming across this issue still, the problem for me was that I was unwittingly passing a null value for the CXHandle in callUpdate - and THEN that I was only checking for nil instead of NSNull.
Old, buggy one:
NSString *callerName = <nullable value from remote message>
CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:handle];
[provider reportNewIncomingCallWithUUID:uuid update:callUpdate completion:^(NSError * _Nullable error) {
...
}]
New, working one
NSString *callerName = <nullable value from remote message>
CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:handle];
if (callerName == (id)[NSNull null] || callerName.length == 0) {
callerName = #"Faceless Man";
}
[provider reportNewIncomingCallWithUUID:uuid update:callUpdate completion:^(NSError * _Nullable error) {
...
}]

how to make voip calls using siri-kit iOS10

I have added extension to app(as per apple documentation) but intent handler class is not responding with my commands. what i am missing don't no.Please help me ,How can i add siri to my app.
// reslove
- (void)resolveContactsForStartAudioCall:(INStartAudioCallIntent *)intent
withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion{
NSArray *contacts;
NSArray * contacts1;
INPersonResolutionResult* result = nil;
if (contacts == intent.contacts) {
for (INPerson *contact in contacts) {
contacts1 = [self contactsMatchingName:contact.displayName];
switch (contacts1.count) {
case 1:
result = [contacts objectAtIndex:0];
[INPersonResolutionResult successWithResolvedPerson:[contacts1 objectAtIndex:0]];
break;
case 0:
result = [INPersonResolutionResult unsupported];
break;
default:
result = [ INPersonResolutionResult disambiguationWithPeopleToDisambiguate:contacts1];
break;
}
}
completion(contacts1);
}else{
result = [INPersonResolutionResult needsValue];
}
}
// confirmation method
- (void)confirmStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
INStartAudioCallIntentResponse *result = nil;
if (![[NSUserDefaults standardUserDefaults]objectForKey:#"isSignedIn"]) {
result = [[INStartAudioCallIntentResponse alloc]initWithCode:INStartAudioCallIntentResponseCodeReady userActivity:nil];
completion(result);
}else{
NSUserActivity *activity = [[NSUserActivity alloc]initWithActivityType:#"reLogin"];
result = [[INStartAudioCallIntentResponse alloc]initWithCode:INStartAudioCallIntentResponseCodeFailure userActivity:activity];
completion(result);
}
}
Here are a few resources to get you started.
Guides and Documentation
SiriKit Programming Guide
Intents Framework
IntentsUI Framework
Sample Code
UnicornChat Sample App
Videos (from WWDC 2016)
Introducing SiriKit
Extending your app with SiriKit

iOS Something going wrong between Singleton, Delegate and SocketIO

I have multiple views where I need to handle the network connection of socket.io, so I created singleton class namely MC_SocketHandler. Below is the code of the MC_SocketHandler class.
// MC_SocketHandler.h
#import <Foundation/Foundation.h>
#import "SocketIO.h"
#interface MC_SocketHandler : NSObject <SocketIODelegate>
// SocketIO
//#property (nonatomic) SocketIO *socketConnection;
+ (MC_SocketHandler *) sharedSocketHanderObj;
+ (SocketIO *) initHandShake;
+ (SocketIO *) getSocketConnection;
-(bool) isConnected;
-(void) disConnect;
-(void) fireAgentLeftChat;
#end
// MC_SocketHandler.m
#import "MC_SocketHandler.h"
#import "MC_APIUtility.h"
#implementation MC_SocketHandler
SocketIO *socketConnection = nil;
static MC_SocketHandler *sharedSocketObj = nil;
+ (MC_SocketHandler *) sharedSocketHanderObj {
if (sharedSocketObj == nil)
sharedSocketObj = [[MC_SocketHandler alloc] init];
return sharedSocketObj;
}
+(SocketIO*) initHandShake {
if (socketConnection == nil) {
NSDictionary *headers = [NSDictionary dictionaryWithObjectsAndKeys:[MC_APIUtility getApiToken], #"token", nil];
socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ];
[socketConnection connectToHost:domain onPort:447 withParams:headers];
}
return socketConnection;
}
+ (SocketIO *) getSocketConnection {
return socketConnection;
}
-(bool) isConnected {
if (socketConnection == nil)
return socketConnection.isConnected;
return false;
}
-(void) disConnect {
if (socketConnection != nil && socketConnection.isConnected)
[socketConnection disconnect];
NSLog(#"Disconnected --- %hhd", socketConnection.isConnected );
return;
}
// SocketIO Delegate
-(void) socketIODidConnect:(SocketIO *)socket {
NSLog(#"Socket has Connected....");
}
-(void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet {
NSString *data = packet.data;
NSLog(#"---- didReceoveEvent - data - %#", data);
// Grab data from packet
NSDictionary *dict = packet.dataAsJSON;
NSLog(#"EVENT DATA :- %# DICT :- %#", data, dict);
/*
EVENTS To Listen
onSuccessInit
visitor_info
new_visitor
agent_online
agent_offline
agent_logout
*/
dict = nil;
// Pull out args fro mdict
//NSArray *args = dict[#"args"];
}
-(void) socketIO:(SocketIO *)socket didReceiveMessage:(SocketIOPacket *)packet {
NSLog(#"Rcvd Message - %#", packet.data);
}
-(void) socketIO:(SocketIO *)socket didSendMessage:(SocketIOPacket *)packet {
NSLog(#"Send Msg - %#", packet.dataAsJSON);
}
-(void) socketIO:(SocketIO *)socket onError:(NSError *)error {
NSLog(#"Error - %#", error);
}
-(void) socketIODidDisconnect:(SocketIO *)socket disconnectedWithError:(NSError *)error {
NSLog(#"Disconnected With Error - %#", error);
}
-(void) fireAgentLeftChat {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[MainAppDataObject sharedAppDataObject].activeAgentChatItem.chatSessionId forKey:#"chat_session_id"];
[socketConnection sendEvent:#"agentLeftChat" withData:dict];
return;
}
- (void)dealloc {
socketConnection = nil;
}
#end
Code that I use it in 1 of my views :
// Init SocketIO
SocketIO *socket = [MC_SocketHandler initHandShake];
// Fire Agent Online event
[socket sendEvent:#"setAgentOnline" withData:nil];
Handshake is being done properly, setAgentOnline event is send properly. Other events that I fire are also done properly. BUT,
when socket gets connected thru initHandshake, I believe "Socket has Connected...." should be seen in logs as that is written in socketIODidConnect delegate method. Similarly, I receive event (I see logs of socket.m class), but my delegate method didReceiveEvent is never called. Same way I don't see any logs of any delegate methods.
In initHandShake method only I have set the delegate also :
socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ];
yet why these methods aren't called.
I was also wondering, when I receive events, on different events I got to perform different actions. How will I transfer to particular view (View's obj won't be shared with this to call his method) ? And If I create delegate, then I will have to handle all delegate methods in all views. What's will be the best method to work out with this ? And why this Singleton & delegate methods aren't being linked & called when I have set the delegate. Where am I going wrong ?
Any help, guidance is highly appreciative. Thanks alot.
In SocketIO, you create a SocketIO
Is that right?
In fact called "socketConnection". Am i right?
AT THAT TIME...
you must set the delegate !!!
Essentially, your code must look like this,
socketConnection = make one of these.
socketConnection.delegate = self;
It's possible this is your fundamental problem. I hope it helps!
PS you should, almost certainly, use only properties in iOS development. get rid of your "traditional" variables and use only properties.

Cocos2D MenuLevel how to lock, unlock

I am using MenuLevel in my game for loading levels.. http://www.prioregroup.com/iphone/menulevel.aspx
At the moment, whether a level is locked or not, it's loading.. If it's locked, it should not be loading.. How can I do that? Thanks..
// create menu item
[menu createMenuItemLevel:1 position:ccp(x, size.height / 2) life:0 locked:NO];
- (void)menuLevel:(MenuLevel *)menuLevel buttonSelected:(id)source
{
CCMenuItem *item = (CCMenuItem*)source;
NSString *msg = [NSString stringWithFormat:#"You have pressed the button # %d", item.tag]; // retrieve level number..
NSLog(#"MenuLevel Sample %#", msg);
// What I want is something like.. if (item.locked == YES) do something
}
You can use the userData property. In your MenuLevel.m file add the following lines in
- (CCMenuItem*)createMenuItemLevel:(NSInteger)level
position:(CGPoint)position
life:(NSInteger)life
locked:(BOOL)locked
target:(id)target
selector:(SEL)selector
method.
if (locked)
{
item.userData = #"locked";
}
else
{
item.userData = #"notLocked";
}
And in your buttonSelected: method check that userData as given below:
NSString *lockString = (NSString *)item.userData;
if ([lockString isEqualToString:#"locked"])
{
// Locked level
}
else
{
// Unlocked
}

Resources