[Windows Store App] Windows Store App with LiveSDK – SignInButton 的注意小事項

在上次文章 [[Windows Store App] Windows Store App with LiveSDK–Single Sign-on] 介紹中,
提到了怎麼利用SignInButton這個控制項,簡單的進行登入Live ID。
但是在Windows Store App中,就只是這樣做的話,
很有可能發生
"無法從應用程式登出,因為使用者帳戶已連結。 (發生例外狀況於 HRESULT: 0x8086000E)"的錯誤訊息....

在上次文章 [[Windows Store AppWindows Store App with LiveSDK–Single Sign-on] 介紹中,
提到了怎麼利用SignInButton這個控制項,簡單的進行登入Live ID。

但是在Windows Store App中,就只是這樣做的話,很有可能發生下面的問題......

狀況開始......

今天某A很開心而且很無聊地依照文章的介紹,拉個一個SignInButton的控制項,
並且順利完成了登入Live ID的動作...

結果在畫面上看到了一個登出的字眼,滑鼠就這樣很順的移了上去,並且按下了滑鼠右鍵.......

鐙!!!!! 發生Exception未處理錯誤! 

無法從應用程式登出,因為使用者帳戶已連結。 (發生例外狀況於 HRESULT: 0x8086000E)

image

怎麼會這樣!!?

 

基本上來說,如果你是使用Live ID來登入Win 8的話,
因為登入動作,是在 作業系統層級中,因此而
Windows Store App這邊,
只是做一個連結,因此並沒有把帳戶登出的權限,所以發生了這樣的錯誤。

然而如果是利用Local 或是 Domain 帳戶登入作業系統的話,則不會發生這樣的錯誤。
(這部分是我個人的理解,如果有誤,或是有更好的解釋,歡迎告訴我 眨眼睛)

關於利用Local 或是 Domain 帳戶登入的話,
在MSDN這篇文件 [
Guidelines for the Microsoft account sign-in experience - Signing users out] 中,
有一段這樣描述著.....

 

Signing users out

In Windows 8 Release Preview, if a user signs in to his or her device with a local or domain
account that is not connected to a Microsoft account, and then signs in to your app with a
Microsoft account, your app should provide a custom sign-out control. For example, the
control could be a label with the text "Sign out" (or its localized equivalent).

Note If the user signs in to the device with a Microsoft account or a local or domain account
that is connected to a Microsoft account, providing a custom sign-out control has no effect.

To determine whether your app should provide a custom sign-out control, your code must
provide the following user experience. First, the user must click the Settings charm and
then click Accounts (or its localized equivalent). After the user clicks the command, and
if the user can sign out, display the custom sign-out control. To do this, use the label
property of the
SettingsCommand class to display the Accounts command (or its
localized equivalent). After the user clicks the command, use the
invoked property to
show a
SettingsFlyout control containing the custom sign-out control; however, if the
user cannot sign out, simply show the current user's name. Here's some example code
showing how to determine whether the current user can sign out.

在 Windows 8 發佈預覽中,如果使用者登錄到本地帳戶或域帳戶未連接到 Microsoft 帳戶,
他或她設備,然後有跡象顯示在您的應用程式使用 Microsoft 帳戶,您的應用程式應提供登出
的自訂控制項。例如,控制項可能會帶有文字標籤"登出"(或其當地語系化的等效)。

請注意如果使用者登錄到 Microsoft 帳戶或本地帳戶或域帳戶連接到 Microsoft 帳戶的設備,
提供登出的自訂控制項沒有任何影響。

若要確定您的應用程式是否應該提供登出的自訂控制項,您的代碼必須提供的以下的使用者體
驗。首先,使用者必須按一下設置魅力,然後按一下帳戶(或其當地語系化的等效)。在使用
者按一下該命令後,如果使用者可以簽,則顯示登出的自訂控制項。若要執行此操作,請使用

SettingsCommand
類的label屬性以顯示帳戶命令 (或其當地語系化的等效)。在使用者
按一下該命令後,使用
調用屬性來顯示包含該自訂的退出控制項 ; SettingsFlyout控制項
但是,如果使用者不能簽,只顯示當前使用者的名稱。下面是一些示例代碼,演示如何確定當
前使用者是否可以簽。

(嗯....很懶的 很順便的直接用Bing翻譯,翻了一下,文辭不通的地方,請自己看原文XDD )

不管怎樣,為了要滿足無論是利用Live ID來登入作業系統,或利用Local 或是 Domain 的話,
勢必需要處理一下,

因此LiveSDK裡提供 OnlineIdAuthenticator.CanSignOut 這個屬性來判斷可否登出,
如果結果是false的話,那就把SignInButton給處理一下啦!!

簡單的處理方法可以參考這樣的方法.....

Step 1  新增SignInButton 控制項
作法可參考文章[[Windows Store AppWindows Store App with LiveSDK–Single Sign-on]  - Step3

Step 2  在MainPage.xaml.cs的MainPage() 裡,則可以這樣做....

public MainPage()
{
    this.InitializeComponent();

    Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator auth = new Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator();
    if (auth.CanSignOut)
    {
        this.btnSignin.Visibility = Windows.UI.Xaml.Visibility.Visible;
    }
    else
    {
        this.btnSignin.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    }
}

此外,除了直接利用SignInButton來處理 Live ID的登入登出動作之外,
當然也可以寫在.cs 中來處理,但記得也要手動處理Logout的部分就是了。

這樣寫的好處,目前玩到現在自己覺得有幾種好處,

  1. 在需要的時候才進行帳戶登入(連結)的動作
  2. 可以同時檢查是否有足夠的權限進行後面的動作
  3. (如果還有其他的好處,或是壞處請留言告訴我來討論吧!!)………

Sample Code 如下....

Step 1 在MainPage.xaml加上一個Button,用於手動登出系統使用 (為了避免混淆,因此名稱使用btnSingOut )
 (記得測試時,要把原本的SignInButton 拿掉,或註解掉)

  <Button x:Name="btnSingOut" Content="登出" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_btnSingOut"/>

Step 2 之後則在MainPage.xaml.cs這樣用.....

private LiveAuthClient auth;
        private LiveConnectClient client;
        private LiveConnectSession session;

        public MainPage()
        {
            this.InitializeComponent();

            //進行授權
            InitAuth();

            //判斷是否可以進行登出動作
            Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator auth = new Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator();
            if (auth.CanSignOut)
            {
                this.btnSingOut.Visibility = Windows.UI.Xaml.Visibility.Visible;
            }
            else
            {
                this.btnSingOut.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            }
        }

        //登入(連結) Live ID 
        private async void InitAuth()
        {
            if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            {
                auth = new LiveAuthClient();
                //這邊來決定所需要權限,同時如果權限有缺的話,會跳出視窗請使用者授權
                LiveLoginResult authResult =
                    await auth.LoginAsync(new List<string>() { "wl.signin", "wl.basic", "wl.birthday" });
                if (authResult.Status == LiveConnectSessionStatus.Connected)
                {
                    this.session = authResult.Session;
                    client = new LiveConnectClient(session);
                    infoTextBlock.Text = "Signed in.";
                }
                else
                {
                    infoTextBlock.Text = "Not signed in.";
                    client = null;
                }
            }
        }

        //手動登出系統
        private void Button_btnSingOut(object sender, RoutedEventArgs e)
        {
            auth.Logout();
        }

 

備註:

如果想測試 CanSignOut 這樣的東西,
簡單的說就是測試是否是利用Live ID 登入作業系統,或是本機帳戶來登入作業系統,
Win8很貼心的就是你可以直接在

[電腦設定] – [使用者]– 很方便地去切換要使用本機帳戶登入,或是使用Microsoft Account登入

image

 

參考連結

  1. Guidelines for the Microsoft account sign-in experience - Signing users out
  2. OnlineIdAuthenticator.CanSignOut | canSignOut property
  3. MSDN 論壇 - SkyDrive SignOut Question.
  4. Metro App - How to detect if logged in with Live ID or Local Account

 


歡迎大家一起到MSDN學習與討論