Jak zalogować się na Facebook w Xamarin.Formularze
Chcę zrobić Xamarin.Projekt formularzy, kierowanie na iOS, Android i Windows Phone.
Moja aplikacja musi uwierzytelniać użytkowników za pomocą Facebook.
Czy powinienem zaimplementować Logowanie dla każdej platformy niezależnie, czy skorzystać z ręcznego przepływu? https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.0
Wolę mieć jedną implementację przepływu logowania i używać go na wszystkich platformach.
How can I get a single implementacja Facebook login flow?
7 answers
Xamarin.Social lub Xamarin.Auth za to. Pozwala na korzystanie z tego samego api niezależnie od platformy.
Jak na razie te biblioteki nie są jeszcze PCL, ale nadal można je wykorzystać z projektu zasobów współdzielonych lub abstrakcji API, którego potrzebujesz w interfejsie i wstrzyknąć za pomocą DependencyService
lub innego kontenera DI.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-08 11:07:52
UPDATE (10/24/17): chociaż ten sposób działania był w porządku kilka lat temu, teraz zdecydowanie opowiadam się za używaniem natywnego interfejsu użytkownika do uwierzytelniania, w przeciwieństwie do metody webview pokazanej tutaj. Auth0 to świetny sposób, aby uzyskać natywne logowanie UI dla aplikacji, przy użyciu różnych dostawców tożsamości: https://auth0.com/docs/quickstart/native/xamarin
EDIT: W końcu umieściłem próbkę do tego na Gihub
I posted an answer Na forach Xamarin.Powtórzę to tutaj.
Zacznijmy od rdzenia aplikacji, Xamarin.Forms PCL project . Twoja App
klasa będzie wyglądać mniej więcej tak:
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();
});
}
}
}
}
Pierwszą rzeczą, na którą należy zwrócić uwagę, jest metoda GetMainPage()
. To mówi aplikacji, który ekran powinien załadować się najpierw po uruchomieniu.
Mamy również prostą właściwość i metodę do przechowywania Token
, która jest zwracana z usługi auth, a także prostą IsLoggedIn
własność.
Jest też właściwość Action; coś, co utknąłem tutaj, aby mieć sposób na implementacje platformy do wykonywania Xamarin.Forms navigation action. Więcej na ten temat później.
Zauważysz też trochę czerwieni w IDE, ponieważ nie stworzyliśmy jeszcze klasy ProfilePage
. Zróbmy to.
Utwórz bardzo prostą klasę ProfilePage
W Xamarin.Forms PCL project . Nawet nie zrobimy z tym nic wymyślnego, bo to będzie zależeć od twoja szczególna potrzeba. Ze względu na prostotę w tej próbce, będzie ona zawierała jedną etykietę:
namespace OAuth2Demo.XForms
{
public class ProfilePage : BaseContentPage
{
public ProfilePage ()
{
Content = new Label () {
Text = "Profile Page",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
}
}
}
Ponownie, prawdopodobnie będziesz miał trochę czerwonego w IDE, ponieważ wydaje się, że brakuje BaseContentPage
klasy. Jedynym celem klasy BaseContentPage
jest zapewnienie, że żaden z ekranów aplikacji nie może być wyświetlany, dopóki użytkownik nie zaloguje się. (w tej uproszczonej wersji demonstracyjnej po prostu przechowujemy informacje o użytkowniku w pamięci, więc musisz ponownie zalogować się za każdym razem, gdy aplikacja jest uruchomiona. W realnej aplikacji, uwierzytelnione informacje o użytkowniku będą przechowywane w pęku kluczy urządzenia, co wyeliminuje konieczność logowania się przy każdym uruchomieniu aplikacji.)
Utwórz klasę BaseContentPage
W Xamarin.Formularze PCL project :
namespace OAuth2Demo.XForms
{
public class BaseContentPage : ContentPage
{
protected override void OnAppearing ()
{
base.OnAppearing ();
if (!App.IsLoggedIn) {
Navigation.PushModalAsync(new LoginPage());
}
}
}
}
Dzieje się tu kilka ciekawych rzeczy:
-
Nadpisujemy metodę
OnAppearing()
, która jest podobna do metody Viewwillappear w kontrolerze iOS UIViewController. Możesz wykonać dowolny kod, który chcesz uruchomić bezpośrednio przed pojawi się ekran. -
Jedyną rzeczą, którą robimy w tej metodzie, jest sprawdzenie, czy użytkownik jest zalogowany. Jeśli nie, to wykonujemy modal push do klasy o nazwie
LoginPage
. Jeśli nie znasz pojęcia modalnego, jest to po prostu widok, który zabiera użytkownika z normalnego przepływu aplikacji w celu wykonania jakiegoś specjalnego zadania; w naszym przypadku, aby wykonać logowanie.
Więc stwórzmy LoginPage
klasę w Xamarin.Formularze Projekt PCL :
namespace OAuth2Demo.XForms
{
public class LoginPage : ContentPage
{
}
}
Czekaj...dlaczego ta klasa nie ma ciała???
Odkąd używamy Xamatinu.Komponent Auth (który wykonuje zadanie budowania i prezentowania widoku sieci Web, który działa z dostarczonymi informacjami OAuth2), w rzeczywistości nie chcemy żadnej implementacji w naszej klasie LoginPage
. Wiem, że to dziwne, ale proszę mi wybaczyć.
LoginPage
w projekcie iOS. W tym miejscu pojawia się koncepcja renderera .
W Xamarin.Formularze, jeśli chcesz udostępnić ekrany i kontrolki specyficzne dla platformy (tzn. ekrany, które nie czerpią swojej zawartości ze stron abstrakcyjnych w Xamarin.Forms PCL project), robisz to za pomocą Rendererów.
Utwórz klasę LoginPageRenderer
na swojej platformie iOS projekt:
[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);
}
}
}
}
Są ważne rzeczy do odnotowania:
-
Linia
[assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]
na górze (i co ważne przed deklaracją przestrzeni nazw) używa Xamarin.Formularze DependencyService . Nie jest to najpiękniejsza rzecz na świecie, bo nie jest to najpiękniejsza rzecz na świecie, ale whatever...it działa. Jest to mechanizm, który "mapuje" naszeLoginPageRenderer
naLoginPage
. -
To jest klasa, w której używamy Xamarin.Auth komponent. Stąd pochodzi odniesienie
OAuth2Authenticator
. -
Po pomyślnym zalogowaniu uruchamiamy Xamarin.Forms navigation via
App.SuccessfulLoginAction.Invoke();
. To prowadzi nas z powrotem doProfilePage
. -
Ponieważ jesteśmy na iOS, wykonujemy całą naszą logikę sinde metody
ViewDidAppear()
.
Utwórz klasę LoginPageRenderer
w swoim projekcie platformy Android}. (zauważ, że nazwa klasy, którą tworzysz, jest identyczna do tego w projekcie iOS, ale tutaj w projekcie Android PageRenderer dziedziczy z klas Androida zamiast klas iOS.)
[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));
}
}
}
Jeszcze raz, rzućmy okiem na kilka ciekawych rzeczy:
-
Linia
[assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]
na górze (i co ważne przed deklaracją przestrzeni nazw) używa Xamarin.Formularze DependencyService . Nie ma tu żadnej różnicy od wersji na iOSLoginPageRenderer
. -
Znowu tu jesteśmy używam Xamarinu.Komponent Auth. Stąd pochodzi odniesienie
OAuth2Authenticator
. -
Podobnie jak w wersji na iOS, po pomyślnym zalogowaniu odpalamy Xamarina.Forms navigation via
App.SuccessfulLoginAction.Invoke();
. To prowadzi nas z powrotem doProfilePage
. -
W przeciwieństwie do wersji iOS, wykonujemy całą logikę wewnątrz metody
OnModelChanged()
zamiastViewDidAppear()
.
...oraz Android:
Aktualizacja: Podałem również szczegółową próbkę na moim blogu: http://www.joesauve.com/using-xamarin-auth-with-xamarin-forms/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Facebook facebook to narzędzie do tworzenia loginu na Facebooku za pomocą natywnego komponentu Facebooka, a nie poprzez webview, jak sugerowane tutaj rozwiązania...........:):):):):):):):):):):):):):) Możesz to sprawdzić pod tym adresem:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-12 11:58:54
IOS 8: dla tych, którzy używają kodu @ NovaJoe i utknęli w widoku, dodaj poniższy kod do obejścia:
bool hasShown;
public override void ViewDidAppear(bool animated)
{
if (!hasShown)
{
hasShown = true;
// the rest of @novaJoe code
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 17:54:01
Oto dobry Xamarin.Próbka uwierzytelniania formularzy. Dokumentacja w kodzie jest ładna. Używa widoku sieci Web do renderowania ekranu logowania, ale możesz wybrać, jaki typ logowania chcesz. Zapisuje również token użytkownika, aby nie musiał ponownie logować się.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 04:04:16
Kolejny dodatek do kodu @ NovaJoe, na iOS8 z Facebook, musisz zmodyfikować klasę renderera jak poniżej, aby zamknąć widok po udanym uwierzytelnieniu.
auth.Completed += (sender, eventArgs) => {
// We presented the UI, so it's up to us to dimiss it on iOS.
/*ważne aby dodać ten wiersz * /
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
}
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-26 05:21:04
Prawidłowa implementacja Pagerendera androidów to:
using System;
using Android.App;
using Android.Content;
using OAuth2Demo.XForms.Android;
using Xamarin.Auth;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinAuth;
[assembly: ExportRenderer(typeof(LoginPage), typeof(LoginPageRenderer))]
namespace OAuth2Demo.XForms.Android
{
public class LoginPageRenderer : PageRenderer
{
public LoginPageRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
// 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: "<Constants.clientId>", // your OAuth2 client id
scope: "<Constants.scope>", // the scopes for the particular API you're accessing, delimited by "+" symbols
authorizeUrl: new Uri("<Constants.authorizeUrl>"), // the auth URL for the service
redirectUrl: new Uri("<Constants.redirectUrl>")); // 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));
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-15 14:27:55