[WindowsPhone] 新版整合Facebook+取得token

2014-07-16

恩,Windows Phone 終於可以跟其他平台一樣整合Facebook 了

終於終於,不過我覺得有可能會再改,不過至少不用像以前一樣要用WebView來導來導去

廢話不多說我們就來看看今天的案例

首先介紹兩個畫面
第一個畫面(MainPage.xaml),點下Facebook LOGIN 按鈕後會開啟安裝的Facebook APP進行授權並取得access token

wp_ss_20140716_0005


取得授權後導回到PageSuccess.xaml,並且呈現Access Token 畫面如下:

wp_ss_20140716_0006

介紹完使用案例後,我們來做一些預備動作

1.首先,因為你要上架APP,所以我們先得知道上架後的APP ID所以我們得先上APP HUBS上面去註冊一隻APP
如下:
aaaaa

建立成功後,這時候不一定要上傳XAP檔案,我們依然可以在詳細資料中,得到應用程式識別碼(APP ID) 這組號碼此範例為 e2e1698b-33b5-45ca-ab59-68e299f61edd
我們把這組號碼記下來

2.進入Facebook Developers (https://developers.facebook.com/ ) 新增一隻APP 並且取得 Facebook APP ID 為 527717103994748
並且左側的地方選取Settings 的部分並且Add Platform
cccccc

選擇Windows App ,分別填入,Windows Phone Store ID 的欄位填入步驟一得到的Windows Phone APP ID
无命名

請注意 這地方的- 符號 要拿掉 所以是 e2e1698b33b545caab5968e299f61edd
這時候設定完成我們來看看程式的部分

3.這時候我們來看看按下 Facebook Loing  Button 所執行的程式


private async void btnFBLogin_Click(object sender, RoutedEventArgs e)
{
 
    string urltoEncode = HttpUtility.UrlEncode("e2e1698b33b545caab5968e299f61edd://authorize");
 
        //URL  FORMAT "fbconnect://authorize?client_id=[FACEBOOK APP ID]&scope=basic_info&redirect_uri=msft-[WP APPID WITHOUT DASH AND ALL LOWCASE]://authorize"
        var launch = 
            await
                Windows.System.Launcher.LaunchUriAsync(
                    new System.Uri(
                        "fbconnect://authorize?client_id=527717103994748&scope=public_profile&redirect_uri=msft-" +
                        urltoEncode));
    
}

其中請注意 其LaunchUriAsync 的啟動位置為 
fbconnect://authorize?client_id=[FACEBOOK 的APP ID]&scope=basic_info&redirect_uri=msft-[Windpws Phone APP ID 全小寫但是需要將-符號拿掉]://authorize
此案例為
fbconnect://authorize?client_id=527717103994748&scope=basic_info&redirect_uri=msft-e2e1698b33b545caab5968e299f61edd://authorize

4.建立起一個UriMapper ,我們在專案中新增一個FBUriMapper 去繼承 UriMapperBase ,用來處理登入回來後我們必須將access token 取出來,關於UriMapper 請參考http://appurl.org/docs/wp8

FBUriMapper.cs:


using System;
using System.Net;
using System.Windows.Navigation;
 
namespace TestFBWP
{
    public class FBUriMapper : UriMapperBase
    {
        private string tempUri;
        public override Uri MapUri(Uri uri)
        {
            tempUri = uri.ToString(); 
            if (tempUri.Contains("access_token"))
            {
                var d = ParseQueryString(tempUri, "access_token");
                return new Uri("/PageSuccess.xaml?facebooktoken="+d, UriKind.Relative);
            }
            else
            {
 
 
            }
 
            return uri;
        }
 
 
        /// <summary>
        /// 取得Query String 的值
        /// 沒有寫得很好但是堪用
        /// </summary>
        /// <param name="query"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private static string ParseQueryString(string query, string key)
        {
            var str = WebUtility.UrlDecode(query);
            var datas = str.Split('&');
            foreach (var d in datas)
            {
                if (d.Contains(key + "="))
                {
                    var q = d.Substring(d.IndexOf(key + "="), d.Length - d.IndexOf(key + "="));
                    return q.Replace(key + "=", "");
                }
            }
            return "";
        }
    }
 
 
}

簡單的說,就是在導入APP的前置期,如果有參數傳入,我們可以在這一個地方攔截到並且讓他去該去的地方,所以如果我判斷導入進來的Uri帶有access_token的參數,我則將它導入到PageSuccess.xaml 並且將access_token變成fcebooktoken的參數傳入。

5.光是寫好自訂的UriMapper是不夠的,你要告訴App你要使用此UriMapper 所以我們開啟App.xmal.cs 在InitializePhoneApplication() 加入這一行 
RootFrame.UriMapper = new FBUriMapper();  使得Code 如下


private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;
 
    // Create the frame but don't set it as RootVisual yet; this allows the splash
    // screen to remain active until the application is ready to render.
    RootFrame = new PhoneApplicationFrame();
    RootFrame.Navigated += CompleteInitializePhoneApplication;
 
    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;
    RootFrame.UriMapper = new FBUriMapper();
    // Handle reset requests for clearing the backstack
    RootFrame.Navigated += CheckForResetNavigation;
 
    // Ensure we don't initialize again
    phoneApplicationInitialized = true;
}

6.開啟WMAppManifest.xml  選擇 Packaging 將 Product ID 改成 {Windows APP Id},通常在專案建立時這邊都是VS會亂給,上架時候這組才會統一,但是我們為了測試,這邊就要先改成一樣,這點要注意
asdasdasdasda

7.接下來我們要開啟WMAppManifest.xml  ,請對該檔案點選滑鼠右鍵並且選取View Code 看到此xml 的原始碼 在</Tokens>的下方加入


 . . . 
</
Tokens>
 <Extensions>
   <Protocol Name="msft-e2e1698b33b545caab5968e299f61edd" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
 </Extensions>

其Protocol 的 Name 的值為 msft-[Windows App Id 全小寫且無-符號]

8.這時候我們來看看導到成功的頁面PageSuccess.xaml 程式碼,我們覆寫掉OnNavigatedTo


protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    //先去檢查是否有傳facebooktoken的參數進來,如果有就將txtToken的Text 呈現此值
    if (NavigationContext.QueryString.ContainsKey("facebooktoken"))
    {
          txtToken.Text =NavigationContext.QueryString["facebooktoken"];
    }
}

差不多這樣就大功告成,我們來看看結果
直接透過內部安裝的Faceboo APP 來驗證
wp_ss_20140716_0004

驗證畫面
wp_ss_20140716_0003

回到APP後的畫面
wp_ss_20140716_0006

打完收工

因為這範例是在好幾個月前寫活力挑戰賽研究的,之後我在整理我現在的Code成為這範例,參考許多國外零碎的文章,很懶得去找,不過基於分享的精神,我把案例跟心得重新整理,希望能夠幫到大家,如果要考慮一些導向的問題,我建議可以使用Isolated Storage 來判斷使用者狀態或是將access token 儲存起來,這都是實作上的小技巧,如果大家有興趣再一起討論吧  :)

附上原始碼





當麻許的超技八 2014 | Donma Hsu Design.