如何在Xamarin.Forms中管理Facebook登录以避免频繁进行身份验证?

时间:2018-04-09 07:01:37

标签: facebook-graph-api xamarin.forms xamarin.ios

我使用以下代码进行Facebook登录并访问用户信息,如专辑和图片。我已使用以下代码设置代码以获取访问令牌。现在,问题是每次用户打开应用程序时我都需要获取访问令牌。但是,一旦用户进行身份验证,应用程序将不会要求验证,直到用户关闭应用程序。但是在用户重新打开应用程序后,它会再次要求进行身份验证。这样,如果用户每次尝试访问专辑或Facebook的任何其他内容时都会要求身份验证,用户就会感到沮丧。

有没有想跳过这个?我的意思是一旦用户提供访问Facebook,应用程序不得要求登录(身份验证)。我将拥有访问令牌,但我不知道如何使用身份验证。因此,我们可以经常避免身份验证。

我的代码:

public class FacebookService : IFacebookService
{

    private readonly string[] permissions = { "public_profile", "email", "user_birthday", "user_photos" };

    public event EventHandler<FacebookUser> LoginCompleted;

    public string Token => AccessToken.CurrentAccessToken.TokenString;

    public void Logout()
    {
        LoginManager manager = new LoginManager();
        manager.LogOut();
    }

    public void LogInToFacebook()
    {
        if (AccessToken.CurrentAccessToken == null)
        {
            ObtainNewToken(LogInToFacebook);
            return;
        }

        var fields = new[] { "name", "email", "birthday", "gender", "picture" };

        var query = $"/me?fields={string.Join(",", fields)}";
        var token = AccessToken.CurrentAccessToken.TokenString;
        var request = new GraphRequest(query, null, token, null, "GET");

        request.Start((connection, result, error) =>
        {
            if (error != null)
            {
                HandleError(error.LocalizedDescription);
            }
            else
            {
                var userInfo = result as NSDictionary;
                var id = userInfo["id"].ToString();
                var email = userInfo["email"].ToString();
                var name = userInfo["name"].ToString();
                var birthday = userInfo["birthday"].ToString();
                var gender = userInfo["gender"].ToString();
                var picture = ((userInfo["picture"] as NSDictionary)["data"] as NSDictionary)["url"].ToString();
                var args = new FacebookUser(id, email, name, birthday, gender, picture);
                LoginCompleted?.Invoke(this, args);
            }
        });
    }

    public async System.Threading.Tasks.Task RequestAlbums(Action<FacebookAlbum[]> callback)
    {
        if (AccessToken.CurrentAccessToken == null)
        {
            ObtainNewTokenForAlbum(callback);
            return;
        }

        using (HttpClient client = new HttpClient())
        {
            try
            {
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                var host = "https://graph.facebook.com/";
                var json = await client.GetStringAsync($"{host}me/albums");
                var data = JObject.Parse(json).First.First.ToString();
                var albums = JsonConvert.DeserializeObject<FacebookAlbum[]>(data);

                var getPhotosTasks = new List<System.Threading.Tasks.Task>();

                foreach (var album in albums)
                    getPhotosTasks.Add(System.Threading.Tasks.Task.Run(() => RequestPhotos(album)));

                await System.Threading.Tasks.Task.WhenAll(getPhotosTasks.ToArray());
                callback(albums);
            }
            catch (Exception ex1)
            {
                HandleError(ex1.Message);
            }
        }
    }

    private void ObtainNewTokenForAlbum(Action<FacebookAlbum[]> callback)
    {
        var login = new LoginManager();

        login.LogInWithReadPermissions(permissions, null, (r, e) =>
        {
            if (e == null && !r.IsCancelled)
            {
                RequestAlbums(callback);
            }
            else
                HandleError(e?.LocalizedDescription);
        });
    }

    private async System.Threading.Tasks.Task RequestPhotos(FacebookAlbum album)
    {
        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);

            try
            {
                var host = "https://graph.facebook.com/";
                var json = await client.GetStringAsync($"{host}{album.Id}/photos?fields=source,picture");
                var data = JObject.Parse(json)["data"].ToString();
                album.Photos = JsonConvert.DeserializeObject<FacebookPicture[]>(data);
            }
            catch (Exception exc)
            {
                HandleError(exc.Message);
            }
        }
    }

    private void ObtainNewToken(Action callback)
    {
        var login = new LoginManager();

        login.LogInWithReadPermissions(permissions, null, (r, e) =>
        {
            if (e == null && !r.IsCancelled)
                callback?.Invoke();
            else
                HandleError(e?.LocalizedDescription);
        });
    }

    private void HandleError(string messageDescription)
    {
        messageDescription = messageDescription ?? "Request was cancelled";
        _notificationService.DisplayNotification(messageDescription, Colors.d8Red);
    }
}

的AppDelegate

public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
    UAirship.TakeOff();
    RegisterServices();
    SetupFacebookSDK();
    FFImageLoading.Forms.Touch.CachedImageRenderer.Init();
    var dummy = new FFImageLoading.Forms.Touch.CachedImageRenderer();

    Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    UIApplication.SharedApplication.StatusBarHidden = false;
    UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);

    _networkManager = new NetworkManager();

    OverrideDefaultListViewCustomActionsColors();

    UAirship.Push.UserPushNotificationsEnabled = true;
    new PhotoAccessChecker();
    return ApplicationDelegate.SharedInstance.FinishedLaunching(uiApplication, launchOptions);
}

void SetupFacebookSDK()
{
    FacebookProfile.EnableUpdatesOnAccessTokenChange(true);
    FacebookSettings.AppID = "000000000049000";
    FacebookSettings.DisplayName = "MyProduct";
}

public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
    return ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation);
}

1 个答案:

答案 0 :(得分:1)

我猜你忘了在AppDelegate中初始化FBSDK。

如果return ApplicationDelegate.SharedInstance.FinishedLaunching (application, launchOptions);已执行FinishedLaunching,请检查您的代码。

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
    Settings.AppID = appId;
    Settings.DisplayName = appName;
    // ...

    // This method verifies if you have been logged into the app before, and keep you logged in after you reopen or kill your app.
    return ApplicationDelegate.SharedInstance.FinishedLaunching (application, launchOptions);
}

public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
    // We need to handle URLs by passing them to their own OpenUrl in order to make the SSO authentication works.
    return ApplicationDelegate.SharedInstance.OpenUrl (application, url, sourceApplication, annotation);
}