Xamarin.iOS에서 SiriKit 구현

이 문서에서는 Xamarin.iOS 앱에서 SiriKit 지원을 구현하는 데 필요한 단계를 설명합니다.

iOS 10을 새롭게 접하는 SiriKit을 사용하면 Xamarin.iOS 앱에서 Siri 및 iOS 디바이스의 지도 앱을 사용하여 사용자가 액세스할 수 있는 서비스를 제공할 수 있습니다. 이 문서에서는 필요한 의도 확장, 의도 UI 확장 및 어휘를 추가하여 Xamarin.iOS 앱에서 SiriKit 지원을 구현하는 데 필요한 단계를 설명합니다.

Siri는 관련 작업에 대한 알려진 작업 그룹인 Do기본 개념과 함께 작동합니다. 앱이 Siri와 상호 작용하는 각 상호 작용은 다음과 같이 알려진 서비스 Do기본 중 하나에 속해야 합니다.

  • 오디오 또는 영상 통화.
  • 타고 예약.
  • 운동 관리.
  • 메시징
  • 사진 검색.
  • 결제를 보내거나 받는 경우

사용자가 앱 확장의 서비스 중 하나와 관련된 Siri를 요청하면 SiriKit는 지원 데이터와 함께 사용자의 요청을 설명하는 Intent 개체를 확장에 보냅니다. 그런 다음 앱 확장은 지정된 의도에 대한 적절한 응답 개체를 생성하여 확장이 요청을 처리하는 방법을 자세히 설명합니다.

이 가이드에서는 SiriKit 지원을 기존 앱에 포함하는 빠른 예제를 제공합니다. 이 예제에서는 Fake MonkeyChat 앱을 사용합니다.

The MonkeyChat icon

MonkeyChat은 각각 화면 이름(예: Bobo)과 연결된 사용자 친구의 연락처 책을 보관하고 사용자가 화면 이름으로 각 친구에게 문자 채팅을 보낼 수 있도록 합니다.

SiriKit을 사용하여 앱 확장

SiriKit 개념 이해 가이드에 표시된 것처럼 SiriKit을 사용하여 앱을 확장하는 데 관련된 세 가지 기본 부분이 있습니다.

Extending the App with SiriKit diagram

여기에는 다음이 포함됩니다.

  1. 의도 확장 - 사용자 응답을 확인하고, 앱이 요청을 처리할 수 있는지 확인하고, 실제로 작업을 수행하여 사용자의 요청을 처리합니다.
  2. 의도 UI 확장 - 선택 사항, Siri 환경의 응답에 사용자 지정 UI를 제공 하 고 사용자의 환경을 보강 하기 위해 Siri에 애플 리 케이 션 UI 및 브랜딩을 가져올 수 있습니다.
  3. - Siri가 작업하는 데 도움이 되도록 사용자별 어휘를 앱에 제공합니다.

이러한 모든 요소와 앱에 포함하는 단계는 아래 섹션에서 자세히 설명합니다.

앱 준비

SiriKit은 확장을 기반으로 하지만 앱에 확장을 추가하기 전에 개발자가 SiriKit 채택을 돕기 위해 수행해야 하는 몇 가지 작업이 있습니다.

공통 공유 코드 이동

먼저 개발자는 앱과 확장 간에 공유될 공통 코드 중 일부를 공유 프로젝트, PCL(이식 가능한 클래스 라이브러리) 또는 네이티브 라이브러리로 이동할 수 있습니다.

확장은 앱이 수행하는 모든 작업을 수행할 수 있어야 합니다. 샘플 MonkeyChat 앱의 관점에서 연락처 찾기, 새 연락처 추가, 메시지 보내기 및 메시지 기록 검색과 같은 항목이 있습니다.

이 공통 코드를 공유 프로젝트, PCL 또는 네이티브 라이브러리로 이동하면 해당 코드를 한 곳에서 쉽게 기본 수 있으며 확장 및 부모 앱이 사용자에게 균일한 환경과 기능을 제공할 수 있습니다.

예제 앱 MonkeyChat의 경우 네트워크 및 데이터베이스 액세스와 같은 데이터 모델 및 처리 코드가 네이티브 라이브러리로 이동됩니다.

다음을 수행합니다.

  1. Mac용 Visual Studio 시작하고 MonkeyChat 앱을 엽니다.

  2. 솔루션 패드에서 솔루션 이름을 마우스 오른쪽 단추로 클릭하고 새 프로젝트 추가>...를 선택합니다.

    Add a new project

  3. iOS>라이브러리>클래스 라이브러리를 선택하고 다음 단추를 클릭합니다.

    Select Class Library

  4. 이름을 입력 MonkeyChatCommon 하고 만들기 단추를 클릭합니다.

    Enter MonkeyChatCommon for the Name

  5. 솔루션 탐색기 기본 앱의 참조 폴더를 마우스 오른쪽 단추로 클릭하고 참조 편집...을 선택합니다. MonkeyChatCommon 프로젝트를 확인하고 확인 단추를 클릭합니다.

    Check the MonkeyChatCommon project

  6. 솔루션 탐색기 기본 앱에서 네이티브 라이브러리로 공통 공유 코드를 끌어옵니다.

  7. MonkeyChat의 경우 기본 앱에서 DataModels 및 Processors 폴더를 네이티브 라이브러리로 끌어옵니다.

    The DataModels and Processors folders in the Solution Explorer

네이티브 라이브러리로 이동된 파일을 편집하고 네임스페이스를 라이브러리의 파일과 일치하도록 변경합니다. 예를 들어 다음으로 변경 MonkeyChat 합니다 MonkeyChatCommon.

using System;
namespace MonkeyChatCommon
{
    /// <summary>
    /// A message sent from one user to another within a conversation.
    /// </summary>
    public class MonkeyMessage
    {
        public MonkeyMessage ()
        {
        }
        ...
    }
}

다음으로, 기본 앱으로 using 돌아가서 앱이 이동된 클래스 중 하나를 사용하는 모든 위치에서 네이티브 라이브러리의 네임스페이스에 대한 문을 추가합니다.

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;
using MonkeyChatCommon;

namespace MonkeyChat
{
    public partial class MasterViewController : UITableViewController
    {
        public DetailViewController DetailViewController { get; set; }

        DataSource dataSource;
        ...
    }
}

확장용 앱 설계

일반적으로 앱은 여러 의도에 등록하며 개발자는 앱이 적절한 수의 의도 확장에 맞게 설계되었는지 확인해야 합니다.

앱에 둘 이상의 의도가 필요한 경우 개발자는 모든 의도 처리를 하나의 의도 확장에 배치하거나 각 의도에 대해 별도의 의도 확장을 만들 수 있습니다.

각 의도에 대해 별도의 의도 확장을 만들도록 선택하면 개발자는 각 확장에서 많은 양의 상용구 코드를 복제하고 많은 양의 프로세서 및 메모리 오버헤드를 만들 수 있습니다.

두 옵션 중에서 선택할 수 있도록 의도 중 일부가 자연스럽게 함께 속하는지 확인합니다. 예를 들어 오디오 및 비디오 호출을 수행한 앱은 유사한 작업을 처리하고 가장 많은 코드 재사용을 제공할 수 있으므로 이러한 의도를 단일 의도 확장에 포함할 수 있습니다.

기존 그룹에 맞지 않는 의도 또는 의도 그룹의 경우 앱 솔루션에 새 의도 확장을 만들어 포함할 수 있습니다.

필수 자격 설정

SiriKit 통합을 포함하는 모든 Xamarin.iOS 앱에는 올바른 자격이 설정되어 있어야 합니다. 개발자가 이러한 필수 자격을 올바르게 설정하지 않으면 iOS 10 시뮬레이터가 SiriKit을 지원하지 않으므로 실제 iOS 10 이상 하드웨어에서 앱을 설치하거나 테스트할 수 없습니다.

다음을 수행합니다.

  1. 솔루션 탐색기 파일을 두 번 클릭하여 Entitlements.plist 편집용으로 엽니다.

  2. 원본 탭으로 전환합니다.

  3. com.apple.developer.siri속성을 추가하고 형식다음으로 Boolean설정하고 값을 다음으로 Yes설정합니다.

    Add the com.apple.developer.siri Property

  4. 변경 내용을 파일에 저장합니다.

  5. 솔루션 탐색기 프로젝트 파일을 두 번 클릭하여 편집용으로 엽니다.

  6. iOS 번들 서명을 선택하고 사용자 지정 권한 필드에서 파일이 선택되어 있는지 확인 Entitlements.plist 합니다.

    Select the Entitlements.plist file in the Custom Entitlements field

  7. 확인 단추를 클릭하여 변경 내용을 저장합니다.

완료되면 앱의 파일은 Entitlements.plist 다음과 같이 표시됩니다(외부 편집기에서 열기).

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.siri</key>
    <true/>
</dict>
</plist>

앱 올바르게 프로비전

Apple이 SiriKit 프레임워크를 중심으로 한 엄격한 보안으로 인해 SiriKit 을 구현하는 모든 Xamarin.iOS 앱에는 올바른 앱 ID와 자격(위 섹션 참조)이 있어야 하며 적절한 프로비전 프로필로 서명해야 합니다.

Mac에서 다음을 수행합니다.

  1. 웹 브라우저에서 계정으로 이동하여 https://developer.apple.com 로그인합니다.

  2. 인증서, 식별자프로필을 클릭합니다.

  3. 프로비전 프로필을 선택하고 앱 ID를 선택한 다음, 단추를 클릭합니다+.

  4. 새 프로필의 이름을 입력합니다.

  5. Apple의 명명 권장 사항에 따라 번들 ID를 입력합니다.

  6. App Services 섹션까지 아래로 스크롤하여 SiriKit을 선택하고 계속 단추를 클릭합니다.

    Select SiriKit

  7. 모든 설정을 확인한 다음 앱 ID를 제출 합니다.

  8. 프로비전 프로필>개발을 선택하고, 단추를 클릭하고+, Apple ID선택한 다음, 계속을 클릭합니다.

  9. 모두 선택, 계속을 차례로 클릭합니다.

  10. [모두 선택]을 다시 클릭한 다음 [계속]을 클릭합니다.

  11. Apple의 명명 제안을 사용하여 프로필 이름을 입력한 다음 계속을 클릭합니다.

  12. Xcode를 시작합니다.

  13. Xcode 메뉴에서 기본 설정을 선택합니다 ...

  14. 계정을 선택한 다음 세부 정보 보기... 단추를 클릭합니다.

    Select Accounts

  15. 왼쪽 아래 모서리에서 모든 프로필 다운로드 단추를 클릭합니다.

    Download All Profiles

  16. 위에서 만든 프로비저닝 프로필이 Xcode에 설치되어 있는지 확인합니다.

  17. 프로젝트를 열어 Mac용 Visual Studio SiriKit 지원을 추가합니다.

  18. 솔루션 탐색기 파일을 두 번 클릭합니다Info.plist.

  19. 번들 식별자가 위의 Apple 개발자 포털에서 만든 식별자와 일치하는지 확인합니다.

    The Bundle Identifier

  20. 솔루션 탐색기 프로젝트를 선택합니다.

  21. 프로젝트를 마우스 오른쪽 단추로 클릭하고 옵션을 선택합니다.

  22. iOS 번들 서명을 선택하고 위에서 만든 서명 ID프로비저닝 프로필을 선택합니다.

    Select the Signing Identity and Provisioning Profile

  23. 확인 단추를 클릭하여 변경 내용을 저장합니다.

Important

SiriKit 테스트는 iOS 10 시뮬레이터가 아닌 실제 iOS 10 하드웨어 디바이스에서만 작동합니다. 실제 하드웨어에서 SiriKit 사용 Xamarin.iOS 앱을 설치하는 데 문제가 있는 경우 필요한 권한, 앱 ID, 서명 식별자 및 프로비저닝 프로필이 Apple 개발자 포털 및 Mac용 Visual Studio 모두 올바르게 구성되었는지 확인합니다.

Siri 권한 부여 요청

앱이 사용자별 어휘를 추가하거나 의도 확장이 Siri에 연결하기 전에 Siri에 액세스하기 위해 사용자의 권한 부여를 요청해야 합니다.

앱의 Info.plist 파일을 편집하고, 원본 보기로 전환하고, 앱에서 NSSiriUsageDescription Siri를 사용하는 방법과 전송할 데이터 형식을 설명하는 문자열 값으로 키를 추가합니다. 예를 들어 MonkeyChat 앱은 "MonkeyChat 연락처가 Siri로 전송됩니다"라고 말할 수 있습니다.

The NSSiriUsageDescription in the Info.plist editor

앱이 RequestSiriAuthorization 처음 시작될 때 클래스의 INPreferences 메서드를 호출합니다. 클래스를 AppDelegate.cs 편집하고 메서드를 FinishedLaunching 다음과 같이 만듭니다.

using Intents;
...

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{

    // Request access to Siri
    INPreferences.RequestSiriAuthorization ((INSiriAuthorizationStatus status) => {
        // Respond to returned status
        switch (status) {
        case INSiriAuthorizationStatus.Authorized:
            break;
        case INSiriAuthorizationStatus.Denied:
            break;
        case INSiriAuthorizationStatus.NotDetermined:
            break;
        case INSiriAuthorizationStatus.Restricted:
            break;
        }
    });

    return true;
}

이 메서드가 처음 호출되면 사용자에게 앱이 Siri에 액세스할 수 있도록 허용하라는 경고가 표시됩니다. 개발자가 위에 추가 NSSiriUsageDescription 한 메시지는 이 경고에 표시됩니다. 사용자가 처음에 액세스를 거부하는 경우 설정 앱을 사용하여 앱에 대한 액세스 권한을 부여할 수 있습니다.

언제든지 앱은 클래스의 메서드 INPreferences 를 호출 SiriAuthorizationStatus 하여 Siri에 액세스하는 앱의 기능을 검사 수 있습니다.

지역화 및 Siri

iOS 디바이스에서 사용자는 Siri에 대한 언어를 선택할 수 있으며, 그 다음에는 시스템 기본값이 다릅니다. 지역화된 데이터로 작업할 때 앱은 클래스의 메서드를 SiriLanguageCodeINPreferences 사용하여 Siri에서 언어 코드를 가져와야 합니다. 예시:

var language = INPreferences.SiriLanguageCode();

// Take action based on language
if (language == "en-US") {
    // Do something...
}

사용자별 어휘 추가

사용자별 어휘는 앱의 개별 사용자에게 고유한 단어 또는 구를 제공합니다. 이러한 항목은 런타임에 기본 앱(앱 확장 아님)에서 사용자에 대한 가장 중요한 사용 우선 순위로 정렬된 순서가 지정된 용어 집합으로 제공되며 목록의 시작 부분에 가장 중요한 용어가 있습니다.

사용자별 어휘는 다음 범주 중 하나에 속해야 합니다.

  • 연락처 이름(연락처 프레임워크에서 관리되지 않음)
  • 사진 태그.
  • 사진 앨범 이름입니다.
  • 운동 이름.

용어를 선택하여 사용자 지정 어휘로 등록하는 경우 앱에 익숙하지 않은 사용자가 오해할 수 있는 용어만 선택합니다. "내 운동" 또는 "내 앨범"과 같은 일반적인 용어를 등록하지 마세요. 예를 들어 MonkeyChat 앱은 사용자의 주소록에 있는 각 연락처와 연결된 애칭을 등록합니다.

앱은 클래스의 INVocabulary 메서드를 호출 SetVocabularyStrings 하고 기본 앱에서 NSOrderedSet 컬렉션을 전달하여 사용자별 어휘를 제공합니다. 앱은 항상 메서드를 RemoveAllVocabularyStrings 먼저 호출하여 새 용어를 추가하기 전에 기존 용어를 제거해야 합니다. 예시:

using System;
using System.Linq;
using System.Collections.Generic;
using Foundation;
using Intents;

namespace MonkeyChatCommon
{
    public class MonkeyAddressBook : NSObject
    {
        #region Computed Properties
        public List<MonkeyContact> Contacts { get; set; } = new List<MonkeyContact> ();
        #endregion

        #region Constructors
        public MonkeyAddressBook ()
        {
        }
        #endregion

        #region Public Methods
        public NSOrderedSet<NSString> ContactNicknames ()
        {
            var nicknames = new NSMutableOrderedSet<NSString> ();

            // Sort contacts by the last time used
            var query = Contacts.OrderBy (contact => contact.LastCalledOn);

            // Assemble ordered list of nicknames by most used to least
            foreach (MonkeyContact contact in query) {
                nicknames.Add (new NSString (contact.ScreenName));
            }

            // Return names
            return new NSOrderedSet<NSString> (nicknames.AsSet ());
        }

        // This method MUST only be called on a background thread!
        public void UpdateUserSpecificVocabulary ()
        {
            // Clear any existing vocabulary
            INVocabulary.SharedVocabulary.RemoveAllVocabularyStrings ();

            // Register new vocabulary
            INVocabulary.SharedVocabulary.SetVocabularyStrings (ContactNicknames (), INVocabularyStringType.ContactName);
        }
        #endregion
    }
}

이 코드를 사용하면 다음과 같이 호출될 수 있습니다.

using System;
using System.Threading;
using UIKit;
using MonkeyChatCommon;
using Intents;

namespace MonkeyChat
{
    public partial class ViewController : UIViewController
    {
        #region AppDelegate Access
        public AppDelegate ThisApp {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructors
        protected ViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do we have access to Siri?
            if (INPreferences.SiriAuthorizationStatus == INSiriAuthorizationStatus.Authorized) {
                // Yes, update Siri's vocabulary
                new Thread (() => {
                    Thread.CurrentThread.IsBackground = true;
                    ThisApp.AddressBook.UpdateUserSpecificVocabulary ();
                }).Start ();
            }
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
        #endregion
    }
}

Important

Siri는 사용자 지정 어휘를 힌트로 처리하고 가능한 한 많은 용어를 통합합니다. 그러나 사용자 지정 어휘의 공간은 제한되어 혼동될 수 있는 용어만 등록하는 것이 중요하므로 등록된 총 용어 수를 최소로 유지합니다.

자세한 내용은 사용자별 어휘 참조 및 Apple의 사용자 지정 어휘 참조를 참조하세요.

앱별 어휘 추가

앱별 어휘는 차량 유형 또는 운동 이름과 같이 앱의 모든 사용자에게 알려질 특정 단어와 구를 정의합니다. 애플리케이션의 일부이므로 파일에 기본 앱 번들의 일부로 정의 AppIntentVocabulary.plist 됩니다. 또한 이러한 단어와 구는 지역화되어야 합니다.

앱별 어휘 용어는 다음 범주 중 하나에 속해야 합니다.

  • 라이드 옵션.
  • 운동 이름.

앱별 어휘 파일에는 두 개의 루트 수준 키가 포함되어 있습니다.

  • ParameterVocabularies필수 - 적용되는 앱의 사용자 지정 용어 및 의도 매개 변수를 정의합니다.
  • IntentPhrases선택 사항 - 에 정의된 사용자 지정 용어를 사용하는 예제 구를 ParameterVocabularies포함합니다.

각 항목은 해당 용어가 ParameterVocabularies 적용되는 ID 문자열, 용어 및 의도를 지정해야 합니다. 또한 단일 용어는 여러 의도에 적용될 수 있습니다.

허용되는 값 및 필수 파일 구조의 전체 목록은 Apple의 앱 어휘 파일 형식 참조를 참조하세요.

앱 프로젝트에 파일을 추가 AppIntentVocabulary.plist 하려면 다음을 수행합니다.

  1. 솔루션 탐색기 프로젝트 이름을 마우스 오른쪽 단추로 클릭하고 새 파일 추가>...를 선택합니다.>iOS:

    Add a property list

  2. 솔루션 탐색기 파일을 두 번 클릭하여 AppIntentVocabulary.plist 편집용으로 엽니다.

  3. 키를 추가하려면 이 + 키를 클릭하고 이름을 다음으로 ParameterVocabularies 설정하고 형식다음으로 Array설정합니다.

    Set the Name to ParameterVocabularies and the Type to Array

  4. 단추를 확장하고 ParameterVocabularies 클릭하고 + 형식을 다음으로 Dictionary설정합니다.

    Set the Type to Dictionary

  5. 새 키를 추가하려면 이 + 키를 클릭하고 이름을ParameterNames로 설정하고 형식다음으로 Array설정합니다.

    Set the Name to ParameterNames and the Type to Array

  6. + 형식 및 값을 사용 가능한 매개 변수 이름 중 하나로 사용하여 새 키를 String 추가하려면 클릭합니다. 예: INStartWorkoutIntent.workoutName

    The INStartWorkoutIntent.workoutName key

  7. 다음 형식ArrayParameterVocabularyParameterVocabularies 사용하여 키에 키를 추가합니다.

    Add the ParameterVocabulary key to the ParameterVocabularies key with the Type of Array

  8. 형식Dictionary을 사용하여 새 키를 추가합니다.

    Add a new key with the Type of Dictionary in Visual Studio for Mac.

  9. 형식StringVocabularyItemIdentifier 사용하여 키를 추가하고 용어에 대한 고유 ID를 지정합니다.

    Add the VocabularyItemIdentifier key with the Type of String and specify a unique ID

  10. 형식Array을 사용하여 VocabularyItemSynonyms키를 추가합니다.

    Add the VocabularyItemSynonyms key with the Type of Array

  11. 형식Dictionary을 사용하여 새 키를 추가합니다.

    Add another new key with the Type of Dictionary in Visual Studio for Mac.

  12. 앱이 VocabularyItemPhraseString 정의하는 형식 및 용어를 사용하여 키를 추가합니다.

    Add the VocabularyItemPhrase key with the Type of String and the term the app are defining

  13. 용어의 VocabularyItemPronunciationString 형식 및 윗주 발음을 사용하여 키를 추가합니다.

    Add the VocabularyItemPronunciation key with the Type of String and the phonetic pronunciation of the term

  14. 형식Array을 사용하여 VocabularyItemExamples키를 추가합니다.

    Add the VocabularyItemExamples key with the Type of Array

  15. 용어의 예제 사용과 함께 몇 가지 String 키를 추가합니다.

    Add a few String keys with example uses of the term in Visual Studio for Mac.

  16. 앱에서 정의해야 하는 다른 사용자 지정 용어에 대해 위의 단계를 반복합니다.

  17. 키를 축소합니다 ParameterVocabularies .

  18. 형식Array을 사용하여 IntentPhrases키를 추가합니다.

    Add the IntentPhrases key with the Type of Array

  19. 형식Dictionary을 사용하여 새 키를 추가합니다.

    Add an additional new key with the Type of Dictionary in Visual Studio for Mac.

  20. 예제의 IntentName 형식String 및 의도를 사용하여 키를 추가합니다.

    Add the IntentName key with the Type of String and Intent for the example

  21. 형식Array을 사용하여 IntentExamples키를 추가합니다.

    Add the IntentExamples key with the Type of Array

  22. 용어의 예제 사용과 함께 몇 가지 String 키를 추가합니다.

    Add a few additional String keys with example uses of the term in Visual Studio for Mac.

  23. 앱에서 예제 사용을 제공해야 하는 의도에 대해 위의 단계를 반복합니다.

Important

AppIntentVocabulary.plist 개발 중에 테스트 디바이스에 Siri에 등록되며 Siri가 사용자 지정 어휘를 통합하는 데 다소 시간이 걸릴 수 있습니다. 따라서 테스터는 업데이트될 때 앱별 어휘를 테스트하기 전에 몇 분 정도 기다려야 합니다.

자세한 내용은 앱별 어휘 참조 및 Apple의 사용자 지정 어휘 참조를 참조하세요.

의도 확장 추가

이제 앱이 SiriKit을 채택할 준비가 되었으므로 개발자는 Siri 통합에 필요한 의도를 처리하기 위해 솔루션에 하나 이상의 의도 확장을 추가해야 합니다.

필요한 각 의도 확장에 대해 다음을 수행합니다.

  • Xamarin.iOS 앱 솔루션에 의도 확장 프로젝트를 추가합니다.
  • 의도 확장 Info.plist 파일을 구성합니다.
  • 의도 확장 기본 클래스를 수정합니다.

자세한 내용은 의도 확장 참조 및 Apple의 의도 확장 만들기 참조를 참조하세요.

확장 만들기

솔루션에 의도 확장을 추가하려면 다음을 수행합니다.

  1. 솔루션 패드에서 솔루션 이름을마우스 오른쪽 단추로 클릭하고 새 프로젝트 추가>...를 선택합니다.

  2. 대화 상자에서 iOS>확장 의도 확장을> 선택하고 다음 단추를 클릭합니다.

    Select Intent Extension

  3. 다음으로 의도 확장의 이름을 입력하고 다음 단추를 클릭합니다.

    Enter a Name for the Intent Extension.

  4. 마지막으로 만들기 단추를 클릭하여 앱 솔루션에 의도 확장을 추가합니다.

    Add the Intent Extension to the apps solution.

  5. 솔루션 탐색기 새로 만든 의도 확장의 참조 폴더를 마우스 오른쪽 단추로 클릭합니다. 앱이 위에서 만든 공통 공유 코드 라이브러리 프로젝트의 이름을 확인하고 확인 단추를 클릭합니다.

    Select the name of the common shared code library project.

앱에 필요한 의도 확장 수(위의 확장용 앱 설계 섹션 기반)에 대해 이 단계를 반복합니다.

Info.plist 구성

앱의 솔루션에 추가된 각 의도 확장에 대해 앱에서 작동하도록 파일에서 Info.plist 구성해야 합니다.

일반적인 앱 확장과 마찬가지로 앱에는 기존 키 NSExtensionNSExtensionAttributes 의도 확장의 경우 구성해야 하는 두 가지 새 특성이 있습니다.

The two new attributes that must be configured

  • IntentsSupported - 필수이며 앱이 의도 확장에서 지원하려는 의도 클래스 이름의 배열로 구성됩니다.
  • IntentsRestrictedWhileLocked - 확장의 잠금 화면 동작을 지정하는 앱의 선택적 키입니다. 앱이 의도 확장에서 사용하기 위해 사용자를 로그인하도록 요구하려는 의도 클래스 이름의 배열로 구성됩니다.

의도 확장의 Info.plist 파일을 구성하려면 솔루션 탐색기 해당 파일을 두 번 클릭하여 편집용으로 엽니다. 그런 다음 원본 보기로 전환한 다음 편집기 NSExtension 에서 키와 NSExtensionAttributes 키를 확장합니다.

IntentsSupported 키를 확장하고 이 확장에서 지원할 의도 클래스의 이름을 추가합니다. 예제 MonkeyChat 앱의 경우 다음을 INSendMessageIntent지원합니다.

앱에서 필요에 따라 사용자가 지정된 의도를 사용하도록 디바이스에 로그온해야 하는 경우 키를 확장하고 IntentRestrictedWhileLocked 액세스가 제한된 의도의 클래스 이름을 추가합니다. 예제 MonkeyChat 앱의 경우 사용자가 로그인하여 채팅 메시지를 보내면 다음을 추가 INSendMessageIntent해야 합니다.

사용 가능한 의도 do기본의 전체 목록은 Apple의 의도 Do기본s 참조를 참조하세요.

Main 클래스 구성

다음으로 개발자는 Siri에 대한 의도 확장의 기본 진입점 역할을 하는 기본 클래스를 구성해야 합니다. 대리자를 준수하는 IINIntentHandler 하위 클래스 INExtension 여야 합니다. 예시:

using System;
using System.Collections.Generic;

using Foundation;
using Intents;

namespace MonkeyChatIntents
{
    [Register ("IntentHandler")]
    public class IntentHandler : INExtension, IINSendMessageIntentHandling, IINSearchForMessagesIntentHandling, IINSetMessageAttributeIntentHandling
    {
        #region Constructors
        protected IntentHandler (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override NSObject GetHandler (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 this;
        }
        #endregion
        ...
    }
}

앱이 의도 확장 기본 클래스인 메서드에서 구현해야 하는 한 가지 단독 메서드가 GetHandler 있습니다. 이 메서드는 SiriKit에서 의도를 전달하고 앱은 지정된 의도의 형식과 일치하는 의도 처리기를 반환해야 합니다.

예제 MonkeyChat 앱은 하나의 의도만 처리하므로 메서드에서 GetHandler 자신을 반환합니다. 확장이 둘 이상의 의도를 처리하는 경우 개발자는 각 의도 형식에 대한 클래스를 추가하고 메서드에 전달된 내용을 기반으로 Intent 여기에 인스턴스를 반환합니다.

해결 단계 처리

해결 단계는 의도 확장이 Siri에서 전달되고 사용자의 대화를 통해 설정된 매개 변수를 명확히 하고 유효성을 검사하는 위치입니다.

Siri에서 전송되는 각 매개 변수에는 메서드가 있습니다 Resolve . 앱은 사용자로부터 올바른 답변을 얻기 위해 Siri의 도움이 필요할 수 있는 모든 매개 변수에 대해 이 메서드를 구현해야 합니다.

예제 MonkeyChat 앱의 경우 의도 확장에는 메시지를 보내는 받는 사람이 하나 이상 필요합니다. 목록의 각 받는 사람에 대해 확장은 다음과 같은 결과를 가질 수 있는 연락처 검색을 수행해야 합니다.

  • 정확히 일치하는 연락처가 하나 있습니다.
  • 일치하는 연락처가 두 개 이상 있습니다.
  • 일치하는 연락처를 찾을 수 없습니다.

또한 MonkeyChat에는 메시지 본문에 대한 콘텐츠가 필요합니다. 사용자가 이를 제공하지 않은 경우 Siri는 사용자에게 콘텐츠에 대한 메시지를 표시해야 합니다.

의도 확장은 이러한 각 사례를 정상적으로 처리해야 합니다.

[Export ("resolveRecipientsForSearchForMessages:withCompletion:")]
public void ResolveRecipients (INSendMessageIntent intent, Action<INPersonResolutionResult []> completion)
{
    var recipients = intent.Recipients;
    // If no recipients were provided we'll need to prompt for a value.
    if (recipients.Length == 0) {
        completion (new INPersonResolutionResult [] { (INPersonResolutionResult)INPersonResolutionResult.NeedsValue });
        return;
    }

    var resolutionResults = new List<INPersonResolutionResult> ();

    foreach (var recipient in recipients) {
        var matchingContacts = new INPerson [] { recipient }; // Implement your contact matching logic here to create an array of matching contacts
        if (matchingContacts.Length > 1) {
            // We need Siri's help to ask user to pick one from the matches.
            resolutionResults.Add (INPersonResolutionResult.GetDisambiguation (matchingContacts));
        } else if (matchingContacts.Length == 1) {
            // We have exactly one matching contact
            resolutionResults.Add (INPersonResolutionResult.GetSuccess (recipient));
        } else {
            // We have no contacts matching the description provided
            resolutionResults.Add ((INPersonResolutionResult)INPersonResolutionResult.Unsupported);
        }
    }

    completion (resolutionResults.ToArray ());
}

[Export ("resolveContentForSendMessage:withCompletion:")]
public void ResolveContent (INSendMessageIntent intent, Action<INStringResolutionResult> completion)
{
    var text = intent.Content;
    if (!string.IsNullOrEmpty (text))
        completion (INStringResolutionResult.GetSuccess (text));
    else
        completion ((INStringResolutionResult)INStringResolutionResult.NeedsValue);
}

자세한 내용은 확인 단계 참조 및 Apple의 해결 및 처리 의도 참조를 참조하세요.

확인 단계 처리

확인 단계는 의도 확장이 사용자의 요청을 이행하기 위한 모든 정보를 포함하는지 확인하기 위해 검사 위치입니다. 앱은 Siri에 무슨 일이 일어날지에 대한 모든 지원 세부 정보를 함께 보내려고 하므로 사용자와 함께 이것이 의도 된 작업임을 확인할 수 있습니다.

[Export ("confirmSendMessage:completion:")]
public void ConfirmSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Verify user is authenticated and the app is ready to send a message.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Ready, userActivity);
    completion (response);
}

자세한 내용은 확인 단계 참조참조하세요.

의도 처리

의도 확장이 실제로 작업을 수행하여 사용자의 요청을 수행하고 결과를 Siri에 다시 전달하여 사용자에게 알릴 수 있는 지점입니다.

public void HandleSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Implement the application logic to send a message here.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Success, userActivity);
    completion (response);
}

public void HandleSearchForMessages (INSearchForMessagesIntent intent, Action<INSearchForMessagesIntentResponse> completion)
{
    // Implement the application logic to find a message that matches the information in the intent.
    ...

    var userActivity = new NSUserActivity (nameof (INSearchForMessagesIntent));
    var response = new INSearchForMessagesIntentResponse (INSearchForMessagesIntentResponseCode.Success, userActivity);

    // Initialize with found message's attributes
    var sender = new INPerson (new INPersonHandle ("sarah@example.com", INPersonHandleType.EmailAddress), null, "Sarah", null, null, null);
    var recipient = new INPerson (new INPersonHandle ("+1-415-555-5555", INPersonHandleType.PhoneNumber), null, "John", null, null, null);
    var message = new INMessage ("identifier", "I am so excited about SiriKit!", NSDate.Now, sender, new INPerson [] { recipient });
    response.Messages = new INMessage [] { message };
    completion (response);
}

public void HandleSetMessageAttribute (INSetMessageAttributeIntent intent, Action<INSetMessageAttributeIntentResponse> completion)
{
    // Implement the application logic to set the message attribute here.
    ...

    var userActivity = new NSUserActivity (nameof (INSetMessageAttributeIntent));
    var response = new INSetMessageAttributeIntentResponse (INSetMessageAttributeIntentResponseCode.Success, userActivity);
    completion (response);
}

자세한 내용은 핸들 스테이지 참조참조하세요.

의도 UI 확장 추가

선택적 의도 UI 확장은 앱의 UI 및 브랜딩을 Siri 환경으로 가져오고 사용자가 앱에 연결되어 있다고 느낄 수 있는 기회를 제공합니다. 이 확장을 통해 앱은 브랜드뿐만 아니라 시각적 개체 및 기타 정보를 대본으로 가져올 수 있습니다.

An example Intents UI Extension output

의도 확장과 마찬가지로 개발자는 의도 UI 확장에 대해 다음 단계를 수행합니다.

  • Xamarin.iOS 앱 솔루션에 의도 UI 확장 프로젝트를 추가합니다.
  • 의도 UI 확장 Info.plist 파일을 구성합니다.
  • 의도 UI 확장 기본 클래스를 수정합니다.

자세한 내용은 의도 UI 확장 참조 및 Apple의 사용자 지정 인터페이스 참조 제공을 참조하세요.

확장 만들기

솔루션에 의도 UI 확장을 추가하려면 다음을 수행합니다.

  1. 솔루션 패드에서 솔루션 이름을마우스 오른쪽 단추로 클릭하고 새 프로젝트 추가>...를 선택합니다.

  2. 대화 상자에서 iOS>확장>의도 UI 확장을 선택하고 다음 단추를 클릭합니다.

    Select Intent UI Extension

  3. 다음으로 의도 확장의 이름을 입력하고 다음 단추를 클릭합니다.

    Enter a Name for the Intent Extension in Visual Studio for Mac.

  4. 마지막으로 만들기 단추를 클릭하여 앱 솔루션에 의도 확장을 추가합니다.

    Add the Intent Extension to the apps solution in Visual Studio for Mac.

  5. 솔루션 탐색기 새로 만든 의도 확장의 참조 폴더를 마우스 오른쪽 단추로 클릭합니다. 앱이 위에서 만든 공통 공유 코드 라이브러리 프로젝트의 이름을 확인하고 확인 단추를 클릭합니다.

    Select the name of the common shared code library project in Visual Studio for Mac.

Info.plist 구성

앱에서 작동하도록 의도 UI 확장의 Info.plist 파일을 구성합니다.

일반적인 앱 확장과 마찬가지로 앱에는 기존 키 NSExtensionNSExtensionAttributes 의도 확장의 경우 구성해야 하는 새 특성이 하나 있습니다.

The one new attribute that must be configured

IntentsSupported 는 필수이며 앱이 의도 확장에서 지원하려는 의도 클래스 이름의 배열로 구성됩니다.

의도 UI 확장의 Info.plist 파일을 구성하려면 솔루션 탐색기 해당 파일을 두 번 클릭하여 편집용으로 엽니다. 그런 다음 원본 보기로 전환한 다음 편집기 NSExtension 에서 키와 NSExtensionAttributes 키를 확장합니다.

The NSExtension and NSExtensionAttributes keys in the editor.

IntentsSupported 키를 확장하고 이 확장에서 지원할 의도 클래스의 이름을 추가합니다. 예제 MonkeyChat 앱의 경우 다음을 INSendMessageIntent지원합니다.

사용 가능한 의도 do기본의 전체 목록은 Apple의 의도 Do기본s 참조를 참조하세요.

Main 클래스 구성

Siri의 의도 UI 확장에 대한 기본 진입점 역할을 하는 기본 클래스를 구성합니다. 인터페이스를 준수하는 IINUIHostedViewController 하위 클래스 UIViewController 여야 합니다. 예시:

using System;
using Foundation;
using CoreGraphics;
using Intents;
using IntentsUI;
using UIKit;

namespace MonkeyChatIntentsUI
{
    public partial class IntentViewController : UIViewController, IINUIHostedViewControlling
    {
        #region Constructors
        protected IntentViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }

        public override void DidReceiveMemoryWarning ()
        {
            // Releases the view if it doesn't have a superview.
            base.DidReceiveMemoryWarning ();

            // Release any cached data, images, etc that aren't in use.
        }
        #endregion

        #region Public Methods
        [Export ("configureWithInteraction:context:completion:")]
        public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
        {
            // Do configuration here, including preparing views and calculating a desired size for presentation.

            if (completion != null)
                completion (DesiredSize ());
        }

        [Export ("desiredSize:")]
        public CGSize DesiredSize ()
        {
            return ExtensionContext.GetHostedViewMaximumAllowedSize ();
        }
        #endregion
    }
}

Siri는 의도 UI 확장 내 인스턴스 UIViewController 의 메서드에 클래스 Configure 인스턴스를 전달 INInteraction 합니다.

이 개체는 INInteraction 확장에 다음 세 가지 주요 정보를 제공합니다.

  1. 처리 중인 Intent 개체입니다.
  2. 의도 확장의 Confirm 메서드 및 Handle 의도 응답 개체입니다.
  3. 앱과 Siri 간의 상호 작용 상태를 정의하는 상호 작용 상태입니다.

인스턴스는 UIViewController Siri와의 상호 작용에 대한 원칙 클래스이며 상속되므로 UIViewControllerUIKit의 모든 기능에 액세스할 수 있습니다.

Siri가 Configure 메서드를 UIViewController 호출하면 보기 컨트롤러가 Siri 코드 조각 또는 지도 카드에서 호스트된다는 내용의 보기 컨텍스트가 전달됩니다.

또한 Siri는 앱이 구성을 완료한 후 앱이 원하는 보기 크기를 반환해야 하는 완료 처리기를 전달합니다.

iOS 디자이너에서 UI 디자인

iOS 디자이너에서 의도 UI 확장의 사용자 인터페이스를 레이아웃합니다. 솔루션 탐색기 확장 프로그램 MainInterface.storyboard 파일을 두 번 클릭하여 편집용으로 엽니다. 필요한 모든 UI 요소를 끌어 사용자 인터페이스를 빌드하고 변경 내용을 저장합니다.

Important

의도 UI 확장UIViewController과 같은 UIButtonsUITextFields 대화형 요소를 추가할 수 있지만 비대화형에서는 의도 UI로 엄격히 금지되며 사용자는 이러한 요소와 상호 작용할 수 없습니다.

사용자 인터페이스 연결

iOS 디자이너에서 만든 의도 UI 확장의 사용자 인터페이스를 사용하여 하위 클래스를 UIViewController 편집하고 다음과 같이 메서드를 재정의 Configure 합니다.

[Export ("configureWithInteraction:context:completion:")]
public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
{
    // Do configuration here, including preparing views and calculating a desired size for presentation.
    ...

    // Return desired size
    if (completion != null)
        completion (DesiredSize ());
}

[Export ("desiredSize:")]
public CGSize DesiredSize ()
{
    return ExtensionContext.GetHostedViewMaximumAllowedSize ();
}

기본 Siri UI 재정의

의도 UI 확장은 항상 UI 맨 위에 있는 앱 아이콘 및 이름과 같은 다른 Siri 콘텐츠와 함께 표시되거나 의도에 따라 단추(예: 보내기 또는 취소)가 아래쪽에 표시될 수 있습니다.

앱이 기본적으로 Siri가 사용자에게 표시하는 정보를 바꿀 수 있는 몇 가지 인스턴스가 있습니다(예: 앱이 기본 환경을 앱에 맞게 조정된 환경으로 바꿀 수 있는 메시징 또는 지도).

의도 UI 확장이 기본 Siri UI UIViewController 의 요소를 재정의해야 하는 경우 서브클래스는 인터페이스를 구현 IINUIHostedViewSiriProviding 하고 특정 인터페이스 요소를 표시하도록 옵트인해야 합니다.

다음 코드를 하위 클래스에 UIViewController 추가하여 의도 UI 확장이 이미 메시지 콘텐츠를 표시하고 있음을 Siri에 알립니다.

public bool DisplaysMessage {
    get {return true;}
}

고려 사항

Apple은 개발자가 의도 UI 확장을 디자인하고 구현할 때 다음 사항을 고려할 것을 제안합니다.

  • 메모리 사용량 주의 - 의도 UI 확장은 일시적이고 짧은 시간 동안만 표시되므로 시스템은 전체 앱에서 사용되는 것보다 더 엄격한 메모리 제약 조건을 적용합니다.
  • 최소 및 최대 보기 크기 고려 - 의도 UI 확장이 모든 iOS 디바이스 유형, 크기 및 방향에서 양호하게 표시되는지 확인합니다. 또한 앱이 Siri로 다시 보내는 원하는 크기는 부여되지 않을 수 있습니다.
  • 유연한 적응형 레이아웃 패턴 사용 - 다시 말하지만, 모든 디바이스에서 UI가 멋지게 보이도록 합니다.

요약

이 문서에서는 SiriKit에 대해 설명했으며, 사용자가 Siri 및 iOS 디바이스에서 지도 앱을 사용하여 액세스할 수 있는 서비스를 제공하기 위해 Xamarin.iOS 앱에 추가하는 방법을 보여 줍니다.