Voice Skills Account Linking UI BizBundle

Last Updated on : 2023-07-13 07:14:39download

Voice Skills Account Linking UI BizBundle provides the custom skills of Alexa and Google Assistant. This allows users to quickly bind voice skills to your app and accelerates the process for you to get WWA certification. The UI BizBundle does not depend on any services.

Preparation

Before you start, make sure that you have performed the following steps:

  1. Before the integration, get familiar with the preparation and process to integrate with the UI BizBundle. For more information, see Integrate with Framework.

    The file thing_custom_config.json is added to your main project directory. Certain settings in this file will be required to enable quick binding of Google Assistant voice skills.

  2. To enable quick binding of voice skills, you must subscribe to Tuya’s value-added services, including Amazon Alexa Skill Account Linking and Google Assistant Action Account Linking.

  3. In the application project, choose Signing & Capabilities > Associated Domains, and set Universal Link to applinks:<your channel identifier>.applink.smart321.com. Then, enable Associated Domains in the certificate on the Apple Developer platform.

  4. With Associated Domains enabled, log in to the Tuya IoT Development Platform. In the left-side navigation pane, choose App > App SDK > Optional Setting, select the target app, click the Certificates tab, and then upload the distribution certificate and provisioning profile.

Configure Amazon Alexa

To authorize navigation to the Alexa app, follow these steps and configure the allowlist:

  • In info.plist of the project, add LSApplicationQueriesSchemes and set the type to Array.
  • In LSApplicationQueriesSchemes, add an item of String and set the value to Alexa.
  • Make sure the total number of items in LSApplicationQueriesSchemes does not exceed 50.

Configure Google Assistant

After you subscribe to Google Assistant Action Account Linking, contact Tuya’s staff to get google_flip_client_id and set the value of google_flip_client_id in the file thing_custom_config.json.

{
    "config": {
        "google_flip_client_id": "您的 google_flip_client_id",
    },
}

Integrate with the UI BizBundle

Add the components of the Voice Skills Account Linking UI BizBundle to the Podfile and run the command pod update.

source "https://github.com/tuya/tuya-private-specs"
source 'https://cdn.cocoapods.org/'
platform :ios, '11.0'

target 'your_target_name' do
  # Adds the UI BizBundle.
  pod 'ThingSmartSkillQuickBindBizBundle'
end

Service protocols

The Voice Skills Account Linking UI BizBundle relies on the implementation of the protocol ThingValueAddedServiceProtocol to provide services. You can view the ThingValueAddedServiceProtocol.h file in the ThingModuleServices component.

#import <Foundation/Foundation.h>
@protocol ThingValueAddedServiceProtocol <NSObject>

/**
 * jump to Amazon link home page
 * @params success callback
 * @params failure callback
 */
- (void)goToAmazonAlexaLinkViewControllerSuccess:(successBoolBlock)success failure:(failureBlock)failure;

/**
 * jump to Google link home page
 * @params success callback
 * @params failure callback
 */
- (void)goToGoogleAssitantLinkViewControllerSuccess:(successBoolBlock)success failure:(failureBlock)failure;

/// Call it inside method application:continueUserActivity:restorationHandler: in Appdelegate.m
- (BOOL)thing_application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^ __nonnull)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler API_AVAILABLE(ios(8.0));

/**
 * Returns third-party binding data.
 * @param result The array.
 * @param failure The failure callback.
 */
- (void)getAllThirdPartyVoiceBindingStatus:(void (^_Nullable)(id _Nullable result))success failure:(failureBlock _Nullable )failure;

/**
 * Calls `getAllThirdPartyVoiceBindingStatus` to get a list of binding data and pass a certain entry from the list to `statusData` to implement unbinding.
 * @param statusData The parameter.
 */
- (void)goToDeactiveViewController:(NSDictionary *_Nullable)statusData;

@end

Things to note

  • Before the call of any API method, make sure that the user has logged in to the app.
  • In the method application:continueUserActivity:restorationHandler: of Appdelegate, implement thing_application:continueUserActivity:restorationHandler:. Otherwise, the callback of navigating to other websites will be failed.

Skills binding

ObjC:

#import <ThingSmartBizCore/ThingSmartBizCore.h>
#import <ThingModuleServices/ThingValueAddedServiceProtocol.h>

id<ThingValueAddedServiceProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingValueAddedServiceProtocol)];

// Navigates to the Alexa skill quick binding page.
[impl goToAmazonAlexaLinkViewControllerSuccess:^(BOOL result) {
    // The loading operation is available.
} failure:^(NSError * _Nonnull error) {
    // The loading operation is available.
}];

// Navigates to the Google Assistant skill quick binding page.
[impl goToGoogleAssitantLinkViewControllerSuccess:^(BOOL result) {
    // The loading operation is available.
} failure:^(NSError * _Nonnull error) {
    // The loading operation is available.
}];

AppDelegate.m
// The callback of navigating to other websites.
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
    id<ThingValueAddedServiceProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingValueAddedServiceProtocol)];
    return [impl thing_application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}

Swift:

let impl = ThingSmartBizCore.sharedInstance().service(of: ThingValueAddedServiceProtocol.self)

// Navigates to the Alexa skill quick binding page.
(impl as AnyObject).go?(toAmazonAlexaLinkViewControllerSuccess: { (result) in
    // The loading operation is available.
}, failure: { (error) in
    // The loading operation is available.
})

// Navigates to the Google Assistant skill quick binding page.
(impl as AnyObject).go?(toGoogleAssitantLinkViewControllerSuccess: { (result) in
    // The loading operation is available.
}, failure: { (error) in
    // The loading operation is available.
})

// The callback of navigating to other websites.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
                let impl = thingSmartBizCore.sharedInstance().service(of: ThingValueAddedServiceProtocol.self)
        return (impl as AnyObject).thing_application?(application, continue: userActivity, restorationHandler: restorationHandler) ?? true
}

Skills unbinding

ObjC:

#import <ThingSmartBizCore/ThingSmartBizCore.h>
#import <ThingModuleServices/ThingValueAddedServiceProtocol.h>

id<ThingValueAddedServiceProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingValueAddedServiceProtocol)];
__weak typeof(impl) weakImpl = impl;
// 1. Get the array of target binding data.
[impl getAllThirdPartyVoiceBindingStatus:^(NSArray *array) {
    if ([array isKindOfClass:[NSArray class]] && array.count > 0) {
        NSDictionary * dic = array.firstObject;
        // 2. Trigger unbinding.
        [weakImpl goToDeactiveViewController:dic];
    }
} failure:^(NSError *error) {

}];

Swift:

Do not use as to implement let impl: ThingValueAddedServiceProtocol = ThingSmartBizCore.sharedInstance().service(of: ThingValueAddedServiceProtocol.self) as!ThingValueAddedServiceProtocol . Otherwise, impl returns nil. Use the following example instead.

let impl = ThingSmartBizCore.sharedInstance().service(of: ThingValueAddedServiceProtocol.self);
// 1. Get the array of target binding data.
(impl as AnyObject).getAllThirdPartyVoiceBindingStatus?({ (list :Any?) in
    if let array :Array = list as? Array<Any> {
        print("test",array);
        // 2. Trigger unbinding.
        let first = array.first;
        (impl as AnyObject).go?(toDeactiveViewController: first as? [AnyHashable : Any]);
    }
}, failure: { (error: Error?) in

})

Feature test

You can test the feature to quickly bind voice skills. For more information, see How to test Alexa and Google account linking feature?