Skip to content

August 2, 2017

Passing data from SiriKit Intent Extension to Cordova

by Joe Kuan

I have a mobile app built with Cordova and Sencha Modern Framework and I have also integrated the app with SiriKit workout domain. So if I speak to my iPhone,

Hey Siri, run a test with MYAPP.

Siri will launch my mobile app and run the test service. In order to do that, I need to be able to pass additional data from my Siri workout Intent handler. So that my Cordova app knows which service to start. For details how to create a SiriKit Intent extension, see this.

Suppose you have added SiriKit Intent into your Xcode project, you should see Intent and IntentUI in your Xcode project like below:

Also it is important to understand the concept between extension and container app (see this). The extension doesn’t share data with the container app and they are executed separately. In order to pass data, both extension and container app must share the same ‘App Group’. Go the ‘Capabilities’ tab on your app target and create an App Group in the form of group.{myorg}.{appname}. The following screenshot shows an App Group is added to the product:

Repeat the same procedure for the Intent target.

In my app, I use the workout domain and only need to implement the start workout method. Here is the implementation for IntentHandler.m:

@interface IntentHandler () <INStartWorkoutIntentHandling>

@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.
    
    return self;
}

#pragma mark - INStartWorkoutIntentHandling

- (void)handleStartWorkout:(INStartWorkoutIntent *)intent
                completion:(void (^)(INStartWorkoutIntentResponse *response))completion {

    INStartWorkoutIntentResponse *response = [[INStartWorkoutIntentResponse alloc]
                                              initWithCode:INStartWorkoutIntentResponseCodeContinueInApp userActivity:nil];
    
    NSUserDefaults *defaults = [[NSUserDefaults alloc]
                                initWithSuiteName: @"group.mycompany.myapp"];
    
    [defaults setObject:@"test" forKey:@"start"];
    
    completion(response);
}
@end

First, we create a workout response object with the response code to tell Siri to continue to our app. Then we bind the specific data into the NSUserDefaults object and invoke the completion code passed to the workout handle function.

The final piece is to fetch this data in our Cordova app which should be placed after deviceready event is fired. Fortunately, there is already a Cordova plugin, app-preferences, which makes accessing the default data with just a few lines of code. Here is an example of reading the data stored in NSUserDefaults:

// Check whether SiriKit extension activates the test service
var prefs = plugins.appPreferences;
var suitePrefs = prefs.suite("group.myorg.myapp");

suitePrefs.fetch(
    function(value) {
        // Activated by voice control
        if (value === 'test') {
            // Clear the auto start
            suitePrefs.remove(function() {}, function() {}, 'start');

            // Run a test service
            // runTest();
        }
    },
    // Error
    function(error) {

    },
    'start'
);

Note: At the time of writing, frankly none of the domains in SiriKit really suits my mobile app need but the workout domain comes the closest. AFAIK, you cannot control what Siri to say but I use another Cordova plugin, Text-to-Speech, to do the speech on the response data for simulating a personal assistance experience.

PS: I know very little in mobile development and especially Objective-C but if you see any mistake, please let me know.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

%d bloggers like this: