Skip to main content

Integrate the iOS SDK in license mode

This guide explains how to integrate the iOS SDK in license mode for device management and authentication. The multimodal SDK supports the license billing mode and two access modes: semi-managed and fully-managed.

1. Modes

To use the multimodal interaction development kit in the License billing mode, integrate the License SDK. For details, see Section 4.

1.1. Semi-hosted mode

Use case: You have your own cloud service and can manage and authenticate your devices. A two-way communication channel exists between your cloud service and devices.
  • Server-side development:
    • See the Cloud API development guide to integrate with the cloud APIs. This service provides APIs for device registration and for obtaining a token.
  • Device-side development:
    • Call the genRegisterReq API of the SDK to obtain a signature for device registration.
    • After obtaining the signature, call your own cloud service to register the device. Your cloud service must integrate the POP SDK.
    • After device registration is complete, call the writeDeviceInfo API of the SDK to write the device information.
    • Call the genGetTokenReq API of the SDK to obtain the data signature for the access token.
    • Call the getToken API of the SDK to obtain the decrypted service interaction token. Use this token for service interactions.

1.2. Fully-hosted mode

Use case: You do not have a cloud service and cannot manage devices. Alibaba Cloud performs device management and authentication.
  • Server-side development:
    • None
  • Device-side development:
    • Call the deviceRegister API of the SDK to register the device.
    • Call the getToken API of the SDK to obtain the service interaction token. Use this token for service interactions.

2. Prerequisites

  • Before you use license mode, create an application on the Model Studio console and purchase a license.
  • The SDK generates a unique device identifier and stores it in the keychain to prevent duplicate device registrations. You can retrieve this identifier by calling DeviceInfoUtils.shared.getDeviceId(). You must either use the logic provided by the SDK to obtain the deviceName or ensure its uniqueness in your own implementation.

3. API

3.1. SDK initialization initialize

This method initializes the SDK for both semi-managed and fully-managed modes. Parameters

Parameter

Type

Required

Description

appId

String

Yes

The application ID. The Model Studio console generates this ID when you create an application.

appSecret

String

Yes

The application secret. The Model Studio console generates this secret when you create an application.

deviceName

String

Yes

The device name. You can use the device's Wi-Fi MAC address or a unique serial number.

callBack

InitCallBack

Yes

The SDK initialization callback. Refer to the InitCallBack object.

InitCallBack object

Return value

Method name

Description

void

success()

Called when initialization is successful.

void

fail(ResultError error)

Called when initialization fails. The error parameter contains failure details.

ResultError object

Parameter

Type

Required

Description

code

int

No

The error code.

message

String

No

A human-readable error description.

Returns None Code example
/// Initializes the SDK.
func initializeExample() {
    let params = InitParams(
        appId: "your_app_id",
        appSecret: "your_app_secret",
        deviceName: "your_device_name_or_uuid"
    )

    // Define the callback class.
    class InitCallback: InitCallBack {
        func success() {
            print("Initialization successful")
        }

        func fail(error: ResultError) {
            print("Initialization failed: \(error.message ?? "unknown error")")
        }
    }

    let callback = InitCallback()
    DeviceAuthClient.companion.instance.initialize(params: params, callBack: callback)
}

3.2. Semi-hosted mode

3.2.1. Device registration APIs

3.2.1.1. Generate device registration request: genRegisterReq
Input parameters:

Parameter

Type

Required

Description

appId

String

Yes

The application ID, generated after you create an application in the Model Studio console.

deviceName

String

Yes

A unique name for the device. Use its Wi-Fi MAC address or serial number.

payMode

String

Yes

The billing method. Valid values: PAYG (Pay-As-You-Go) and LICENSE (license-based billing).

reqNonce

String

Yes

A 26-character nonce for the request.

requestTime

String

Yes

The request timestamp, in milliseconds.

Output parameters:

Parameter

Type

Required

Description

success

boolean

Yes

Indicates whether the request was successful.

code

int

No

The error code returned if the request fails.

message

String

No

The error message returned if the request fails.

data

String

No

The signature required to call the POP API for device registration.

Sample code:
/// Semi-hosted mode: Generate a signature for a device registration request.
func genRegisterReqExample() {
        let registerInfo = DeviceRegisterInfo(
            reqNonce: "random_nonce_string",
            appId: "your_app_id",
            deviceName: "your_device_name",
            payMode: PayMode.license.payMode,
            requestTime: "\(Int64(Date().timeIntervalSince1970 * 1000))"
        )

        let result = DeviceAuthClient.companion.instance.genRegisterReq(registerInfo: registerInfo)

    if result.success {
            let signature = result.data
            print("Successfully generated registration signature: \(signature ?? "")")
            // Use the signature to call your server-side registration API.
        } else {
            print("Failed to generate registration signature: \(result.message)")
        }
    }
3.2.1.2. Write device registration information: writeDeviceInfo
The response from the device registration POP API must be passed to the device-side SDK to write the device information. Input parameters:

Parameter

Type

Required

Description

appId

String

Yes

The application ID, generated after you create an application in the Model Studio console.

deviceName

String

Yes

A unique name for the device. Use its Wi-Fi MAC address or serial number.

reqNonce

String

Yes

The nonce from the original registration request.

rspNonce

String

Yes

A 26-character nonce from the server response.

responseTime

String

Yes

The timestamp from the server response, in milliseconds.

signature

String

Yes

YOUR_SIGNATURE
Output parameters:

Parameter

Type

Required

Description

success

boolean

Yes

Indicates whether the request was successful.

code

int

No

The error code returned if the request fails.

message

String

No

The error message returned if the request fails.

data

String

No

Not used.

Sample code:
/// Semi-hosted mode: Write the device registration information.
func writeDeviceInfoExample() {
    let deviceInfo = DeviceRegisterRsp(
        appId: "your_app_id",
        reqNonce: "request_nonce",
        rspNonce: "response_nonce_from_server",
        responseTime: "response_time_from_server",
        deviceName: "your_device_name",
        signature: "signature_from_server"
    )

    let result = DeviceAuthClient.companion.instance.writeDeviceInfo(deviceInfo: deviceInfo)

    if result.success {
        print("Successfully wrote device information")
    } else {
        print("Failed to write device information: \(result.message)")
    }
}

3.2.2. APIs for obtaining an access token

3.2.2.1. Generate access token request: genGetTokenReq
Input parameters:

Parameter

Type

Required

Description

nonce

String

Yes

A 26-character nonce for the request.

appId

String

Yes

The application ID, generated after you create an application in the Model Studio console.

deviceName

String

Yes

A unique name for the device. Use its Wi-Fi MAC address or serial number.

payMode

String

Yes

The billing method. Valid values: PAYG (Pay-As-You-Go) and LICENSE (license-based billing).

tokenType

String

Yes

The type of token to request. The only currently supported value is MMI.

The MMI value specifies a multimodal interaction token.

requestTime

String

Yes

The request timestamp, in milliseconds.

Output parameters:

Parameter

Type

Required

Description

success

boolean

Yes

Indicates whether the request was successful.

code

int

No

The error code returned if the request fails.

message

String

No

The error message returned if the request fails.

data

String

No

The signature required to call the server-side API to obtain an access token.

{
    "success": true,
    "data": "84uoRCyy6AG/SH7LrHjJW0D7lsBp/H4RReS7gJY5L0oC517xJWAmwtmghLjYkW/Qj4ZvK6vrM7QC5yxtMl3TQLHdAGSsqQLb0bP6zKOiDzoNFwqs61+GMQ7guTPjbE9Fqaf7"
}
Sample code:
/// Semi-hosted mode: Generate a signature for an access token request.
func genGetTokenReqExample() {
     let getTokenParams = GenGetTokenParams(
         nonce: "random_nonce_string",
         appId: "your_app_id",
         deviceName: "your_device_name",
         payMode: PayMode.license.payMode,
         requestTime: "\(Int64(Date().timeIntervalSince1970 * 1000))",
         signature: nil, // Generated by the SDK
         tokenType: "MMI"
     )

     let result = DeviceAuthClient.companion.instance.genGetTokenReq(getTokenParams: getTokenParams)

     if result.success {
         let signature = result.data
         print("Successfully generated token request signature: \(signature ?? "")")
         // Use the signature to call your server-side API to get the access token.
     } else {
         print("Failed to generate token request signature: \(result.message)")
     }
 }
3.2.2.2. Extract access token: getToken
Input parameters:

Parameter

Type

Required

Description

appId

String

Yes

The application ID, generated after you create an application in the Model Studio console.

deviceName

String

Yes

A unique name for the device. Use its Wi-Fi MAC address or serial number.

reqNonce

String

Yes

The nonce from the original access token request.

rspNonce

String

Yes

A 26-character nonce from the server response.

responseTime

String

Yes

The timestamp from the server response, in milliseconds.

signature

String

Yes

YOUR_SIGNATURE
Output parameters:

Parameter

Type

Required

Description

success

boolean

Yes

Indicates whether the request was successful.

code

int

No

The error code returned if the request fails.

message

String

No

The error message returned if the request fails.

data

String

No

The resulting access token.

Sample code:
/// Semi-hosted mode: Process the server response to get the access token.
func getTokenWithSignatureExample() {
    let tokenRsp = AnalyzeTokenSignRsp(
        reqNonce: "request_nonce",
        rspNonce: "response_nonce_from_server",
        responseTime: "response_time_from_server",
        appId: "your_app_id",
        deviceName: "your_device_name",
        signature: "signature_from_server"
    )

    let result = DeviceAuthClient.companion.instance.getToken(tokenRsp: tokenRsp)

    if result.success {
        let token = result.data
        print("Successfully obtained token: \(token ?? "")")
        // Use the access token for subsequent service calls.
    } else {
        print("Failed to get token: \(result.message)")
    }
}

3.3. Fully managed mode

3.3.1. Check device registration: deviceIsRegistered

Parameters: None Returns: Returns true if the device is registered, or false otherwise. Code example:
/// Checks if the device is registered.
func checkDeviceRegisteredExample() {
    let isRegistered = DeviceAuthClient.companion.instance.deviceIsRegistered()

    if isRegistered {
        print("Device is registered.")
    } else {
        print("Device is not registered. Register the device first.")
    }
}

3.3.2. Register a device: deviceRegister

Parameters:

Parameter

Type

Required

Description

params

Object

Yes

Device registration parameters. For details, see the DeviceRegisterParams object.

callBack

DeviceRegisterCallBack

Yes

The callback that handles the device registration result.

DeviceRegisterParams object

Parameter

Type

Required

Description

nonce

String

Yes

A 26-character random string.

appId

String

Yes

The application ID, generated by Model Studio when you create an application in the console.

workspaceId

String

No

The workspace ID. Required only when registering a device using a workspace quota.

deviceName

String

Yes

A unique device name, such as its Wi-Fi MAC address or serial number.

requestTime

String

Yes

The request timestamp, in milliseconds.

payMode

String

Yes

The billing method. Set to PAYG for Pay-As-You-Go or LICENSE for license-based billing.

Returns: None Code example:
/// fully managed mode: Device registration
func deviceRegisterExample() {
    let params = DeviceRegisterParams(
        nonce: "random_nonce_string",
        appId: "your_app_id",
        workspaceId:"your_workspace_id"
        deviceName: "your_device_name",
        payMode: PayMode.license.payMode,
        requestTime: "\(Int64(Date().timeIntervalSince1970 * 1000))",
        signature: nil
    )

    // Define the callback class.
    class DeviceRegisterCallback: DeviceRegisterCallBack {
        func success() {
            print("Device registration successful")
        }

        func fail(error: ResultError) {
            print("Device registration failed: \(error.message ?? "unknown error")")
        }
    }

    let callback = DeviceRegisterCallback()
    DeviceAuthClient.companion.instance.deviceRegister(
        params: params,
        callBack: callback,
        completionHandler: { _ in }
    )
}

3.3.3. Get multimodal interaction token: getToken

Parameters:

Parameter

Type

Default

Required

Description

params

Object

-

Yes

Parameters for getting a token. For details, see the GenGetTokenParams object.

callBack

GetTokenCallBack

-

Yes

The callback that handles the token retrieval result. For details, see the GetTokenCallBack object.

GenGetTokenParams object

Parameter

Type

Default

Required

Description

nonce

String

-

Yes

A 26-character random string.

appId

String

-

Yes

The application ID, generated by Model Studio when you create an application in the console.

apiKey

String

-

Yes

The API key. Create one in Key Management on the Model Studio console.

deviceName

String

-

Yes

The unique identifier of the device.

requestTime

String

-

Yes

The request timestamp, in milliseconds.

payMode

String

-

Yes

The billing method. Set to PAYG for Pay-As-You-Go or LICENSE for license-based billing.

tokenType

String

-

Yes

The type of token to request. Only MMI (multimodal interaction token) is currently supported.

MMI: multimodal interaction token

Returns: None Code example:
/// fully managed mode: Get a token
func getTokenFullManagedExample() {
    let params = GenGetTokenParams(
        nonce: "random_nonce_string",
        appId: "your_app_id",
        deviceName: "your_device_name",
        payMode: PayMode.license.payMode,
        requestTime: "\(Int64(Date().timeIntervalSince1970 * 1000))",
        signature: nil,
        tokenType: "MMI"
    )

    // Define the callback class.
    class GetTokenCallback: GetTokenCallBack {
        func success(tokenInfo: String?) {
            print("Token retrieved successfully: \(tokenInfo ?? "")")
        }

        func fail(error_ error: ResultError?) {
            print("Failed to retrieve token: \(error?.message ?? "unknown error")")
        }
    }

    let callback = GetTokenCallback()
    DeviceAuthClient.companion.instance.getToken(
        params: params,
        callBack: callback,
        completionHandler: { _ in }
    )
}

3.4. Get license signatures

Input parameters:

Parameter

Type

Default

Required

Description

params

Object

-

Yes

Parameters for device authentication. See the LicenseSignatureParams object for details.

LicenseSignatureParams object

Parameter

Type

Default

Required

Description

appId

String

-

Yes

The application ID. The Model Studio console provides this ID after you create an application.

deviceName

String

-

Yes

The unique device identifier.

taskId

String

-

Yes

The client generates this unique identifier to track task execution in the task pipeline. A 36-character UUID is recommended, for example: "f894c16f-f20e-4c1d-837e-89e0fbc63a43".

Output parameters:

Parameter

Type

Default

Description

timestamp

String

-

The current timestamp in milliseconds.

license_info

String

-

The signature for the license information.

device_info

String

-

The signature for the device information.

Usage example:
/// Get the license signature.
func getLicenseSignatureExample() {
    let params = LicenseSignatureParams(
        appId: "your_app_id",
        deviceName: "your_device_name",
        taskId: "your_task_id"
    )

    let licenseSignature = DeviceAuthClient.companion.instance.getLicenseSignature(params: params)
    print("License signature result: \(licenseSignature)")
    // Returns a JSON string with the timestamp, and the signatures for license_info and device_info.
}

3.5. deviceReset

Note: After resetting a device in the Model Studio console, you must call the SDK's deviceReset API before registering it again. Parameters: None Return value: A boolean. Returns true if the reset was successful. Example:
 let result = DeviceAuthClient.companion.instance.deviceReset()
 if(result){
     print("Device reset successful")
 }else{
     print("Device reset failed")
 }

4. Integrate dependency library

Reference the MultimodalDialogTongyiMetathings.framework from the latest iOS SDK.

5. Multimodal SDK integration

  1. Before starting a session, initialize the tongyimetathings SDK and check if the device is registered. If not, register the device. For details, see the sample integration project.
  2. After initializing the SDK and registering the device, get a multimodal session token. See sections 2.1 and 2.3 for the required interfaces. Set the apiKey parameter to the dashToken value returned by the getToken interface. See the sample project for details.
chatView.updateParam(url: host, apiKey: dashToken, workSpaceId: workSpaceId, appId: appId, chain: chainMode, image_url: img, payType: self.mPayMode, voice: voice)
  1. When creating a session, pass the license billing identifier. See the following code for a reference implementation:
func connect(){
    self.conversation?.stop()
    isInDialog = false

    var mode = DialogMode.duplex
    if(!duplexMode){
        mode = DialogMode.tap2talk
    }
    let taskId = UUID().uuidString.replacingOccurrences(of: "-", with: "").lowercased()
    let promptParam = ["user_name" : "Dami"]
    TYLogger.shared.debug("current voice:" + voice)
    var params:MultiModalRequestParam
            // Build the license billing identifier
            let deviceName = DeviceInfoUtils.shared.getDeviceId()
            let licenseParams = LicenseSignatureParams(appId: self.APP_ID, deviceName: deviceName, taskId: taskId)
            let signData = DeviceAuthClient.companion.instance.getLicenseSignature(params: licenseParams)
            print("signData: \(signData)")
             // Convert the JSON string to a dictionary
            guard let data = signData.data(using: .utf8),
                  let signatureJson = try? JSONSerialization.jsonObject(with: data) else {
                print("Failed to parse signData as JSON")
                return
            }
            let map: [String: Any] = ["signature": signatureJson]

            params = MultiModalRequestParam{ multiBuilder in
               multiBuilder.upStream = MultiModalRequestParam.UpStream(builder: { upstreamBuilder in
                   upstreamBuilder.mode = mode.rawValue
                   upstreamBuilder.type = "AudioAndVideo"
               })

               multiBuilder.clientInfo = MultiModalRequestParam.ClientInfo(builder: {
                   clientInfoBuilder in
                   clientInfoBuilder.userId = "test-ios-user"
                   clientInfoBuilder.device = MultiModalRequestParam.ClientInfo.Device(uuid: deviceName)
                   clientInfoBuilder.passThroughParams = map
               })
               multiBuilder.downStream = MultiModalRequestParam.DownStream(builder: {
                   downStreamBuilder in
                   downStreamBuilder.sampleRate = 16000
                   downStreamBuilder.voice = voice
                   downStreamBuilder.intermediateText = textStreamFeedback ? "dialog" : "transcript"
               })
               multiBuilder.bizParams = MultiModalRequestParam.BizParams(builder: {
                   bizBuilder in
                   bizBuilder.userPromptParams = promptParam
               })
           }
}
Agent Development
Agent Context
Agent Governance & Evolution
Store
Application Marketplace