How-To指南:與圖形通知整合 (iOS)

Graph 通知可讓應用程式跨多個裝置來傳送及管理使用者鎖定的通知。

當 iOS 上有 Project Rome 用戶端 SDK 時,iOS 應用程式就可以進行註冊,以接收應用程式伺服器所發佈、對象為已登入使用者的通知。 此 SDK 可讓應用程式用戶端接收新的傳入通知承載、管理現有通知的狀態,以及擷取通知歷程記錄。 如需通知本身及其如何能夠以人為中心來傳遞通知的詳細資訊,請參閱 Microsoft Graph 通知概觀

Project Rome SDK 中的所有功能 (包括 Graph 通知等) 會以稱為連線裝置平台的基礎平台作為建置基礎。 本指南旨在帶領您完成必要步驟以便開始使用連線裝置平台,並說明如何取用 SDK 中的 API 來實作 Graph 通知專用的功能。

下列步驟會參考來自 Project Rome iOS 應用程式範例的程式碼 (可在 GitHub 上取得)。

請參閱 API 參考頁面,來取得通知案例相關參考文件的連結。

設定連線裝置平台和通知

註冊您的應用程式

Project Rome SDK 的功能幾乎都需要 Microsoft 帳戶 (MSA) 或 Azure Active Directory (AAD) 驗證 (鄰近分享 API 除外)。 如果您還沒有 MSA 但想要使用,請在 account.microsoft.com 上註冊。

注意

裝置轉送 API 則不支援 Azure Active Directory (AAD) 帳戶。

使用所選擇的驗證方法時,您必須遵循應用程式註冊入口網站上的指示,向 Microsoft 註冊應用程式。 如果您沒有 Microsoft 開發人員帳戶,則必須建立一個。

當您使用 MSA 註冊應用程式時,應該會收到用戶端識別碼字串。 請儲存此字串以供稍後使用。 此字串可讓應用程式存取 Microsoft 的連線裝置平台資源。 如果您使用 AAD,請參閱 Azure Active Directory 驗證程式庫來找到有關如何取得用戶端識別碼字串的指示。

新增 SDK

若要將連線裝置平台新增至 iOS 應用程式,最簡單的方式是使用 CocoaPods 相依性管理員。 請移至 iOS 專案的「Podfile」,並插入下列項目:

platform :ios, "10.0"
workspace 'iOSSample'

target 'iOSSample' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

	pod 'ProjectRomeSdk'

  # Pods for iOSSample

注意

為了取用 CocoaPod,您必須使用專案中的 .xcworkspace 檔案。

設定驗證和帳戶管理

連線裝置平台需要有效的 OAuth 權杖以便在註冊程序中使用。 您可以使用您慣用的方法來產生及管理 OAuth 權杖。 不過,為了協助開發人員開始使用該平台,我們已在 iOS 應用程式範例中加入驗證提供者,以供您在應用程式中產生和管理重新整理權杖。

如果您未使用提供的程式碼,則必須自行實作 MCDConnectedDevicesAccountManager 介面。

如果您使用 MSA,請在登入要求中加入下列領域︰"wl.offline_access""ccs.ReadWrite""dds.read""dds.register""wns.connect""asimovrome.telemetry""https://activity.windows.com/UserActivity.ReadWrite.CreatedByApp"

注意

裝置轉送 API 則不支援 Azure Active Directory (AAD) 帳戶。

如果您使用 AAD 帳戶,則必須要求下列對象:"https://cdpcs.access.microsoft.com""https://cs.dds.microsoft.com""https://wns.windows.com/""https://activity.microsoft.com"

如果您使用提供的MCDConnectedDevicesAccountManager實作,如果您使用 AAD,則必須在 azure Active Directory > Azure 入口網站 (portal.azure.com > 應用程式註冊) 上的應用程式註冊中指定下列許可權:

  • Microsoft 活動摘要服務
    • 傳遞並修改此應用程式的使用者通知
    • 在使用者的活動摘要中讀取及寫入應用程式活動
  • Windows 通知服務
    • 將裝置連線到 Windows 通知服務
  • Microsoft 裝置目錄服務
    • 查看裝置清單
    • 務必新增至裝置和應用程式的清單
  • Microsoft 命令服務
    • 與使用者裝置通訊
    • 讀取使用者裝置

針對推播通知註冊應用程式

向 Apple 註冊應用程式以獲得 Apple Push Notification 支援。 請務必記下您所收到的寄件者識別碼和伺服器金鑰,因為稍候需要用到這些資料。

註冊之後,您必須讓推播通知功能與應用程式中的連線裝置平台相關聯。

self.notificationRegistration = [[MCDConnectedDevicesNotificationRegistration alloc] init];
    if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
    {
        self.notificationRegistration.type = MCDNotificationTypeAPN;
    }
    else
    {
        self.notificationRegistration.type = MCDNotificationTypePolling;
    }
    self.notificationRegistration.appId = [[NSBundle mainBundle] bundleIdentifier];
    self.notificationRegistration.appDisplayName = (NSString*)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
    self.notificationRegistration.token = deviceToken;
    self.isRegisteredWithToken = YES;

在 Microsoft Windows 開發人員中心註冊應用程式以獲得跨裝置體驗

警告

只有在想要使用 Project Rome 功能來從非 Windows 裝置中存取資料或對非 Windows 裝置提出要求時,才需要執行這個步驟。 如果您只以 Windows 裝置作為目標,則不需要完成此步驟。

請註冊應用程式以獲得 Microsoft 開發人員儀表板的跨裝置體驗功能。 這個程序與上述的 MSA 和 AAD 應用程式註冊不同。 這個程序的主要目的是要讓平台特有的應用程式身分識別與連線裝置平台所辨識的跨平台應用程式身分識別相對應。 此步驟也會讓您能夠使用與應用程式所利用行動平台相對應的原生推播通知服務來傳送通知。 在 iOS 中,其可讓通知透過 APNS (Apple Push Notification Service) 來傳送至 iOS 應用程式端點。

請移至開發人員中心儀表板、從左側瀏覽窗格瀏覽至跨裝置體驗,然後選取要設定新的跨裝置應用程式。 開發人員中心儀表板 – 跨裝置體驗

開發人員中心的上線程序需要執行下列步驟:

  • 選取支援的平台 – 選取會出現應用程式並為應用程式啟用跨裝置體驗的平台。 在 Graph 通知整合的案例中,您可以根據所使用的平台來選取 Windows、Android 及/或 iOS。 跨裝置體驗 – 支援的平臺

  • 提供應用程式識別碼 – 針對所使用的每個平台提供應用程式識別碼。 若為 iOS 應用程式,此識別碼是您在建立專案時指派給應用程式的套件名稱。 請注意,您可以為每個平台新增不同的識別碼 (最多十個) – 這是為了讓同一個應用程式的多個版本 (或甚至是不同的應用程式),能夠接收應用程式伺服器傳送給同一位使用者的相同通知。 跨裝置體驗 – 應用程式識別碼

  • 提供應用程式識別碼或從上面先前的 MSA/AAD 應用程式註冊步驟所取得的 MSA 及/或 AAD 應用程式註冊選取應用程式識別碼。 跨裝置體驗 – MSA 和 AAD 應用程式註冊

  • 請針對與應用程式相關的原生通知平台提供認證 (亦即,Windows 的 WNS、Android 的 FCM 及/或 iOS 的 APNS),以便在您發佈目標為使用者的通知時,能夠從應用程式伺服器傳遞通知。 跨裝置體驗 – 推送認證

  • 最後,請驗證跨裝置應用程式網域,以確保應用程式具有網域的擁有權,並可使用網域來作為應用程式的跨裝置身分識別。 跨裝置體驗 – 網域驗證

使用平台

建立平台的執行個體

以開始直接具現化平台。

MCDConnectedDevicesPlatform* platform = [MCDConnectedDevicesPlatform new];

訂閱 MCDConnectedDevicesAccountManager

此平台需要已驗證的使用者才能存取平台。 您必須訂閱 MCDConnectedDevicesAccountManager 事件,以確保會使用有效帳戶。

[MCDConnectedDevicesPlatform* platform.accountManager.accessTokenRequested
     subscribe:^(MCDConnectedDevicesAccountManager* _Nonnull manager __unused,
                 MCDConnectedDevicesAccessTokenRequestedEventArgs* _Nonnull request __unused) {

                    // Get access token

                 }
[MCDConnectedDevicesPlatform* platform.platform.accountManager.accessTokenInvalidated
     subscribe:^(MCDConnectedDevicesAccountManager* _Nonnull manager __unused,
                 MCDConnectedDevicesAccessTokenInvalidatedEventArgs* _Nonnull request) {

                      // Refresh and renew existing access token

                 }

訂閱 MCDConnectedDevicesNotificationRegistrationManager

同樣地,此平台會使用通知在裝置之間傳遞命令。 因此,您必須訂閱 MCDConnectedDevicesNotificationRegistrationManager 事件,以確保雲端註冊狀態適用於所使用的帳戶。 使用 MCDConnectedDevicesNotificationRegistrationState 確認狀態

[MCDConnectedDevicesPlatform* platform.notificationRegistrationManager.notificationRegistrationStateChanged
     subscribe:^(MCDConnectedDevicesNotificationRegistrationManager* manager __unused,
                 MCDConnectedDevicesNotificationRegistrationStateChangedEventArgs* args __unused) {

                     // Check state using MCDConnectedDevicesNotificationRegistrationState enum

                 }

啟動平台

既然平台已初始化且已備妥事件處理常式,您就準備好可以開始探索遠端系統裝置。

[MCDConnectedDevicesPlatform* platform start];

擷取應用程式已知的使用者帳戶

請務必要確保應用程式已知的使用者帳戶清單有正確地與 MCDConnectedDevicesAccountManager 同步。

使用 MCDConnectedDevicesAccountManager.addAccountAsync 來新增新的使用者帳戶。

[MCDConnectedDevicesPlatform* platform.accountManager
     addAccountAsync:self.mcdAccount
     callback:^(MCDConnectedDevicesAddAccountResult* _Nonnull result, NSError* _Nullable error) {

     // Check state using **MCDConnectedDevicesAccountAddedStatus** enum

     }

若要移除無效帳戶,您可以使用 MCDConnectedDevicesAccountManager.removeAccountAsync

 [MCDConnectedDevicesPlatform* platform.accountManager
     removeAccountAsync:existingAccount
     callback:^(MCDConnectedDevicesRemoveAccountResult* _Nonnull result __unused, NSError* _Nullable error) {

                    // Remove invalid user account

     }

初始化 Graph 通知通道

Project Rome SDK 可讓應用程式訂閱不同通道,以便接收及管理各種類型的使用者資料,包括 Graph 通知、使用者活動等等。 這些資料全都會儲存在 MCDUserDataFeed 內並進行同步處理。 MCDUserNotification 是透過 Graph 通知所傳送、與鎖定使用者的通知相對應的類別和資料類型。 若要與 Graph 通知整合並開始接收應用程式伺服器所發佈的 MCDUserNotification,您必須先藉由建立 MCDUserNotificationChannel 來初始化使用者資料摘要。 此程序的處理方式應該和上面的平台初始化步驟一樣:應該進行檢查,並可能要在每次應用程式移到前景時 (但不要在平台初始化之前) 重做。

下列方法會初始化 MCDUserNotificationChannel

// You must be logged in to use UserNotifications
NSArray<MCDUserAccount*>* accounts = [[AppDataSource sharedInstance].accountProvider getUserAccounts];
if (accounts.count > 0)
{
    // Get a UserNotification channel, getting the default channel
    NSLog(@"Creating UserNotificationChannel");
    NSArray<MCDUserAccount*>* accounts = [[AppDataSource sharedInstance].accountProvider getUserAccounts];
    MCDUserDataFeed* userDataFeed = [MCDUserDataFeed userDataFeedForAccount:accounts[0]
        platform:[AppDataSource sharedInstance].platform
        activitySourceHost:CROSS_PLATFORM_APP_ID];
    NSArray<MCDSyncScope*>* syncScopes = @[ [MCDUserNotificationChannel syncScope] ];
    [userDataFeed addSyncScopes:syncScopes];
    self.channel = [MCDUserNotificationChannel userNotificationChannelWithUserDataFeed:userDataFeed];
}
else
{
    NSLog(@"Must log in to receive notifications for the logged in user!");
    self.createNotificationStatusField.text = @"Need to be logged in!";
}

此時,channel 中應該會有 MCDUserNotificationChannel 參考。

建立 MCDUserNotificationReader 來接收傳入的 MCDUserNotification 並存取 MCDUserNotification 歷程記錄

和之前的示範一樣,這個抵達應用程式用戶端的初始 APNS 無聲訊息只包含拍肩提醒,您必須將該拍肩提醒承載傳遞到連線裝置平台,才能觸發 SDK 而使其執行以連線裝置伺服器 (內含應用程式伺服器所發佈的所有 MCDUserNotification) 為對象的完整同步處理。 這會將此拍肩提醒對應的應用程式伺服器所發佈的完整通知承載拉下來 (如果此應用程式用戶端由於裝置連線或其他問題而未收到任何先前已發佈的通知,則這些通知也會一起拉下來)。 由於 SDK 會持續不斷地執行即時的同步處理,應用程式用戶端因此可以存取這位登入使用者的 MCDUserNotification 資料摘要本機快取。 在此情況下,MCDUserNotificationReader 可讓應用程式用戶端存取此資料摘要,而能夠透過事件接聽程式接收最新的通知承載,或能夠存取可作為使用者通知歷程記錄檢視模型的完整 MCDUserNotification 集合。

接收 MCDUserNotification

首先您必須具現化 MCDUserNotificationReader,如果您想要針對所嘗試啟用的體驗來取用讀取器中所有既有的 MCDUserNotification,則還要先取得該資訊。 由於這個特定的裝置端點可能不是使用者已安裝您應用程式的唯一或第一個端點,因此您可以一律放心地假設應用程式伺服器已發佈通知給這位登入使用者。 然後,請新增事件接聽程式,以便在連線裝置平台完成同步處理並且有要讓您知道的新變更時觸發。 在 Graph 通知的案例中,新變更可以是應用程式伺服器所發佈的傳入 MCDUserNotification,也可以是該伺服器或同一位使用者所登入其他已註冊端點所發生的 MCDUserNotifcation 更新、刪除和到期。

提示

此事件接聽程式可讓您處理主要的商務邏輯,並根據案例來「取用」通知承載的內容。 如果您目前使用 APNS 無聲通知在 OS 層級的通知中心內建構視覺通知,或如果您使用無聲通知中的內容來更新某些應用程式內 UI,便可使用此事件接聽程式來進行相關操作。

// Instantiate the reader from a MCDUserNotificationChannel
// Add a data change listener to subscribe to new changes when new notifications or notification updates are received
- (void)setupWithAccount:(MCDUserAccount*)account {
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
        @synchronized (self) {
            MCDUserDataFeed* dataFeed = [MCDUserDataFeed userDataFeedForAccount:account platform:_platform activitySourceHost:@"graphnotifications.sample.windows.com"];
            [dataFeed addSyncScopes:@[[MCDUserNotificationChannel syncScope]]];
            self.channel = [MCDUserNotificationChannel userNotificationChannelWithUserDataFeed:dataFeed];
            self.reader = [self.channel createReader];
            
            __weak typeof(self) weakSelf = self;
            _readerRegistrationToken = [self.reader addDataChangedListener:^(__unused MCDUserNotificationReader* source) {
                NSLog(@"ME123 Got a change!");
                if (weakSelf) {
                    [weakSelf forceRead];
                } else {
                    NSLog(@"ME123 WEAKSELF FOR CHANGES IS NULL!!!");
                }
            }];
            
            [self forceRead];
        }
    });
}

// this is your own business logic when the event listener is fired
// In this case, the app reads the existing batch of notifications in the store and handle any new incoming notifications or notification updates after that
- (void)forceRead {
    NSLog(@"ME123 Forced to read!");
    [self.reader readBatchAsyncWithMaxSize:NSUIntegerMax completion:^(NSArray<MCDUserNotification *> * _Nullable notifications, NSError * _Nullable error) {
        if (error) {
            NSLog(@"ME123 Failed to read batch with error %@", error);
        } else {
            [self _handleNotifications:notifications];
            NSLog(@"ME123 Have %ld listeners", self.listenerMap.count);
            for (void (^listener)(void) in self.listenerMap.allValues) {
                NSLog(@"ME123 Calling a listener about an update!");
                listener();
            }
        }
    }];
}

更新現有 MCDUserNotification 的狀態

在上一節中,我們提到透過讀取器收到的 MCDUserNotification 變更有時候可能會是現有 MCDUserNotification 的狀態更新 (不論標示為已關閉或標示為已讀取)。 在此情況下,應用程式用戶端可以選擇要執行的操作,例如藉由在這個特定裝置上移除對應的視覺通知來啟用通用關閉。 退一步來說,這個可作為操作起點的 MCDUserNotification 變更更新,往往是由應用程式用戶端所起始 (從不同的裝置)。 您可以選擇要更新 MCDUserNotification 狀態的時間,但其更新時機通常是對應的視覺通知是由該裝置上的使用者處理時,或使用者在您啟用的某些應用程式內體驗進一步處理通知時。 以下是流程外觀的範例:您的應用程式伺服器會發佈以使用者 A 為目標的通知。使用者 A 會在其電腦及其安裝應用程式用戶端的手機上收到此通知。 使用者在電腦上按一下通知,並進入應用程式來處理對應的工作。 此電腦上的應用程式用戶端隨即會呼叫連線裝置平台 SDK 來更新對應使用者通知的狀態,以便讓此更新同步處理到這位使用者的所有裝置。 其他應用程式用戶端則會在收到此狀態更新時,即時地從裝置的通知中心/通知匣/控制中心移除對應的視覺警示/訊息/快顯通知。 這便是通知在使用者的所有裝置上全面關閉的方式。

提示

MCDUserNotification 類別目前提供 2 種狀態更新,您可以修改 MCDUserNotificationReadState 或 MCDUserNotificationUserActionState 並定義您自己的邏輯來指出通知有所更新時應該如何處理。 例如,您可以將動作狀態標示為已啟用或已關閉,並根據該值來實作通用關閉。 或者,您也可以同時將讀取狀態標示為已讀取或未讀取,並據此決定應該在應用程式內的通知歷程記錄檢視中顯示哪些通知。

- (void)dismissNotification:(MCDUserNotification*)notification {
    @synchronized (self) {
        notification.userActionState = MCDUserNotificationUserActionStateDismissed;
        [notification saveAsync:^(__unused MCDUserNotificationUpdateResult * _Nullable result, __unused NSError * _Nullable err) {
            NSLog(@"ME123 Dismiss notification with result %d error %@", result.succeeded, err);
        }];
    }
}