如何login到Xamarin.Forms的Facebook

我想做一个Xamarin.Forms项目,瞄准iOs,Android和Windows Phone。

我的应用需要使用Facebook对用户进行身份validation。

我应该为每个平台独立实现login,还是使用手动stream程? https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.0

我更喜欢有一个loginstream的实现,并在所有平台上使用它。

我怎样才能得到一个facebookloginstream的实现?

你可以使用Xamarin.Social或Xamarin.Auth 。 它允许使用相同的API,无论平台是什么。

到目前为止,这些库并不是PCL,但你仍然可以从共享资源项目中使用它们,或者在接口中抽象出你需要的API,然后使用DependencyService或任何其他DI容器注入。

更新(10/24/17):虽然这种做法在几年前是好的,但我现在强烈主张使用本机UI进行身份validation,而不是这里显示的webview方法。 通过使用各种各样的身份提供者,Auth0是完成您的应用的原生用户界面login的绝佳方式: https : //auth0.com/docs/quickstart/native/xamarin

编辑:我终于把这个样品在Gihub

我在Xamarin论坛上发布了一个答案。 我会在这里重复一遍。

我们从应用程序的核心Xamarin.Forms PCL项目开始 。 你的App类看起来像这样:

 namespace OAuth2Demo.XForms { public class App { static NavigationPage _NavPage; public static Page GetMainPage () { var profilePage = new ProfilePage(); _NavPage = new NavigationPage(profilePage); return _NavPage; } public static bool IsLoggedIn { get { return !string.IsNullOrWhiteSpace(_Token); } } static string _Token; public static string Token { get { return _Token; } } public static void SaveToken(string token) { _Token = token; } public static Action SuccessfulLoginAction { get { return new Action (() => { _NavPage.Navigation.PopModalAsync(); }); } } } } 

首先要注意的是GetMainPage()方法。 这告诉应用程序启动时应该先加载哪个屏幕。

我们也有一个简单的属性和方法来存储从auth服务返回的Token ,以及一个简单的IsLoggedIn属性。

还有一个Action属性, 东西我坚持在这里为了有一个平台的实现Xamarin.Forms导航行动的方式。 稍后再说。

您还会在IDE中注意到一些红色,因为我们还没有创buildProfilePage类。 那么,让我们来做。

Xamarin.Forms PCL项目中创build一个非常简单的ProfilePage类。 我们甚至不会去做任何事情,因为这取决于你的特殊需求。 为了简单起见,它将包含一个标签:

 namespace OAuth2Demo.XForms { public class ProfilePage : BaseContentPage { public ProfilePage () { Content = new Label () { Text = "Profile Page", VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.CenterAndExpand, }; } } } 

同样,你可能会在你的IDE中有一些红色,因为我们似乎错过了BaseContentPage类。 BaseContentPage类的唯一目的是确保应用程序的屏幕都不会显示,直到用户login。 (在这个简化的演示,我们只是坚持用户信息内存,所以你需要重新 – 每次运行应用程序时,在真实世界的应用程序中,您将存储经过身份validation的用户信息到设备的钥匙串,这将消除在每次应用程序启动时需要login的情况。

Xamarin.Forms PCL项目中创build一个BaseContentPage类:

 namespace OAuth2Demo.XForms { public class BaseContentPage : ContentPage { protected override void OnAppearing () { base.OnAppearing (); if (!App.IsLoggedIn) { Navigation.PushModalAsync(new LoginPage()); } } } } 

这里有一些有趣的事情:

  1. 我们重写了OnAppearing()方法,它类似于iOS UIViewController中的ViewWillAppear方法。 你可以在这里执行任何你想在屏幕出现之前立即运行的代码。

  2. 我们在这个方法中唯一要做的就是检查用户是否login。如果他们不是,那么我们执行一个模式推送到一个名为LoginPage的类。 如果您不熟悉模式的概念,那么它只是一个视图,它将用户从正常的应用程序stream程中移出以执行一些特殊的任务; 在我们的情况下,执行login。

所以,我们在Xamarin.Forms PCL项目中创buildLoginPage类:

 namespace OAuth2Demo.XForms { public class LoginPage : ContentPage { } } 

等等…为什么这个class没有身体?

由于我们使用Xamatin.Auth组件(它负责构build和呈现一个可以与提供的OAuth2信息一起工作的Web视图),我们实际上并不希望在LoginPage类中实现任何types的实现。 我知道这似乎很奇怪,但忍受着我。

适用于iOS的LoginPageRenderer

到目前为止,我们一直在Xamarin.Forms PCL项目中工作 。 但是现在我们需要在iOS项目中提供我们LoginPage的平台特定实现。 这是渲染器的概念来的地方。

在Xamarin.Forms中,当您想要提供平台特定的屏幕和控件(即不从Xamarin.Forms PCL项目的抽象页面中获取其内容的屏幕)时,您可以使用Renderer进行操作

iOS平台项目中创build一个LoginPageRenderer类:

 [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))] namespace OAuth2Demo.XForms.iOS { public class LoginPageRenderer : PageRenderer { public override void ViewDidAppear (bool animated) { base.ViewDidAppear (animated); var auth = new OAuth2Authenticator ( clientId: "", // your OAuth2 client id scope: "", // the scopes for the particular API you're accessing, delimited by "+" symbols authorizeUrl: new Uri (""), // the auth URL for the service redirectUrl: new Uri ("")); // the redirect URL for the service auth.Completed += (sender, eventArgs) => { // We presented the UI, so it's up to us to dimiss it on iOS. App.SuccessfulLoginAction.Invoke(); if (eventArgs.IsAuthenticated) { // Use eventArgs.Account to do wonderful things App.SaveToken(eventArgs.Account.Properties["access_token"]); } else { // The user cancelled } }; PresentViewController (auth.GetUI (), true, null); } } } } 

有一些重要的事情需要注意:

  1. 在顶部(最重要的是命名空间声明之前 [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))][assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]行正在使用Xamarin.Forms DependencyService 。 这不是世界上最美丽的东西,因为它不是IoC / DI,但是无论什么…它的工作。 这是将我们的LoginPageRenderer “映射”到LoginPage

  2. 这是我们实际使用Xamarin.Auth组件的类。 这就是OAuth2Authenticator引用来自的地方。

  3. 一旦login成功,我们通过App.SuccessfulLoginAction.Invoke();引发Xamarin.Forms导航App.SuccessfulLoginAction.Invoke(); 。 这让我们回到ProfilePage

  4. 由于我们在iOS上,我们正在做ViewDidAppear()方法的所有逻辑sinde。

Android的LoginPageRenderer

Android平台项目中创build一个LoginPageRenderer类。 (请注意,您创build的类名与iOS项目中的类名相同,但是在Android项目中,PageRenderer从Android类inheritance,而不是从iOS类inheritance。)

 [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))] namespace OAuth2Demo.XForms.Android { public class LoginPageRenderer : PageRenderer { protected override void OnModelChanged (VisualElement oldModel, VisualElement newModel) { base.OnModelChanged (oldModel, newModel); // this is a ViewGroup - so should be able to load an AXML file and FindView<> var activity = this.Context as Activity; var auth = new OAuth2Authenticator ( clientId: "", // your OAuth2 client id scope: "", // the scopes for the particular API you're accessing, delimited by "+" symbols authorizeUrl: new Uri (""), // the auth URL for the service redirectUrl: new Uri ("")); // the redirect URL for the service auth.Completed += (sender, eventArgs) => { if (eventArgs.IsAuthenticated) { App.SuccessfulLoginAction.Invoke(); // Use eventArgs.Account to do wonderful things App.SaveToken(eventArgs.Account.Properties["access_token"]); } else { // The user cancelled } }; activity.StartActivity (auth.GetUI(activity)); } } } 

再次,让我们看看一些有趣的事情:

  1. 在顶部(最重要的是命名空间声明之前 [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))][assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]行正在使用Xamarin.Forms DependencyService 。 与iOS版本的LoginPageRenderer没有什么不同。

  2. 再次,这是我们实际使用Xamarin.Auth组件的地方。 这就是OAuth2Authenticator引用来自的地方。

  3. 就像iOS版本一样,一旦login成功,我们通过App.SuccessfulLoginAction.Invoke();引发Xamarin.Forms导航App.SuccessfulLoginAction.Invoke(); 。 这让我们回到ProfilePage

  4. 与iOS版本不同,我们正在执行OnModelChanged()方法内部的所有逻辑,而不是ViewDidAppear()

这里是在iOS上:

Xamarin.Auth与Xamarin.Forms iOS示例

…和Android:

Xamarin.Auth与Xamarin.Forms Android示例

更新:我也在我的博客提供了一个详细的示例: http : //www.joesauve.com/using-xamarin-auth-with-xamarin-forms/

我已经创build了一个示例项目来展示如何使用本地Facebook组件创buildFacebooklogin,而不是像本文中提供的解决scheme那样通过webview。 你可以在这个地址查看:

https://github.com/IdoTene/XamarinFormsNativeFacebook

IOS 8:对于那些正在使用@NovaJoe代码并被困在视图中的人,请将代码添加到解决方法:

  bool hasShown; public override void ViewDidAppear(bool animated) { if (!hasShown) { hasShown = true; // the rest of @novaJoe code } } 

这是一个很好的Xamarin.Formsauthentication示例。 代码中的文档很好。 它使用webview来呈现login屏幕,但是你可以select你想要的logintypes。 它还保存了一个用户令牌,所以他不必保持重新login。

https://github.com/rlingineni/Xamarin.Forms_Authentication

在iOS8上使用Facebook的另一个@ NovaJoe代码,你需要修改Renderer类,如下所示,在authentication成功后closuresView。

 auth.Completed += (sender, eventArgs) => { // We presented the UI, so it's up to us to dimiss it on iOS. 

/ *导入并添加此行* /

  DismissViewController (true, null); 

/ * * /

  if (eventArgs.IsAuthenticated) { App.Instance.SuccessfulLoginAction.Invoke (); // Use eventArgs.Account to do wonderful things App.Instance.SaveToken (eventArgs.Account.Properties ["access_token"]); } else { // The user cancelled } };