Reputation:
I am using xamarin.forms for my app. It allows the user to log in via facebook. I have added a logout button in the app to simply navigate back to the login page but i noticed that when i exit my app without pressing the logout button, the app resumes at the login page( causing the user to keep entering their login details everytime they have to re-open the app). How can I keep the user logged in when they close and reopen the app? Any guidance on this will be appreciated..
App.cs (MainPage is my login page)
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
public async static Task NavigateToSMS()
{
await App.Current.MainPage.Navigation.PushAsync(new SMS());
}
public static void NavigateToProfile()
{
App.Current.MainPage = (new InvalidLogin());
}
public static void NavigateToVerified()
{
App.Current.MainPage = (new Profile());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app sleeps
}
FacebookRender
[assembly: ExportRenderer(typeof(Login), typeof(LoyaltyWorx.Droid.FacebookRender))]
namespace LoyaltyWorx.Droid
{
public class FacebookRender : PageRenderer
{
public FacebookRender()
{
String error;
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "",
scope: "email",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
try
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me?fields=email,first_name,last_name,gender,picture"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["first_name"].ToString().Replace("\"", "");
var surname = obj["last_name"].ToString().Replace("\"", "");
var gender = obj["gender"].ToString().Replace("\"", "");
var email = obj["email"].ToString().Replace("\"", "");
Customer.Customers cust = new Customer.Customers();
cust.Number = "";
cust.Name = name;
cust.Surname = surname;
cust.Address = "sample";
cust.Email = email;
cust.City = "DBN";
cust.Region = "KZN";
cust.Country = "SA";
cust.MobilePhone = " ";
cust.DOB = DateTime.Now;
cust.Phone = " ";
cust.Credentials = new Customer.Credentials();
cust.Credentials.Authenticated = true;
cust.Credentials.SecretKey = "73fnfdbjfdj";
cust.DeviceToken = GcmService.RegistrationID;
CustomerService service = new CustomerService();
Settings.Token = await service.AddCustomer(cust);
if (Settings.MobileNo == null || Settings.MobileNo == " ")
{
await App.NavigateToSMS();
}
else
{
App.NavigateToVerified();
}
}
else
{
App.NavigateToProfile();
}
}
catch(Exception ex)
{
error = ex.Message;
}
};
activity.StartActivity(auth.GetUI(activity));
}
}
}
The Page that comes up after user is signed in
namespace LoyaltyWorx
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Profile : MasterDetailPage
{
public List<MasterPageItem> menuList { get; set; }
public Profile()
{
InitializeComponent();
this.lblMessage.Text = Settings.Name + " " + Settings.Surname;
menuList = new List<MasterPageItem>();
var page1 = new MasterPageItem() { Title = "Home", Icon = "home.png", TargetType = typeof(Page1) };
var page2 = new MasterPageItem() { Title = "Cards", Icon = "card.png", TargetType = typeof(Cards) };
var page3 = new MasterPageItem() { Title = "Transactions", Icon = "settings.png", TargetType = typeof(Transactions) };
var page4 = new MasterPageItem() { Title = "My Profile", Icon = "profile.png", TargetType = typeof(UpdateProfile) };
var page5 = new MasterPageItem() { Title = "Log out", Icon = "signout.png", TargetType = typeof(MainPage) };
menuList.Add(page1);
menuList.Add(page2);
menuList.Add(page3);
menuList.Add(page4);
menuList.Add(page5);
navigationDrawerList.ItemsSource = menuList;
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(Page1)));
}
private void OnMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (MasterPageItem)e.SelectedItem;
Type page = item.TargetType;
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsPresented = false;
}
}
}
Settings Class: Stores logged in user's details
public static class Settings
{
public static string Token;
public static int CustId;
public static string Name;
public static string Surname;
public static string Email;
public static string MobileNo;
public static string PhoneNo;
}
App.cs - Update
public App()
{
App.Current.Properties["UserDetail"] = Settings.Token;
InitializeComponent();
var isLoggedIn = Current.Properties.ContainsKey("UserDetail");
if (!isLoggedIn)
{
MainPage = new NavigationPage(new MainPage());
}
else
{
App.Current.MainPage = (new Profile());
}
}
Upvotes: 0
Views: 7383
Reputation: 2604
On every app launch you are loading the MainPage
. You have to load the first page conditionally.
Xamarin.Forms implements Application.Current.Properties which stores the key value data in the local storage of the app.
On Login:
On Successful login, Store "True" value in the application's local storage in some key like IsLoggedIn
as follows:
Application.Current.Properties ["IsLoggedIn"] = Boolean.TrueString;
On App Launch (App.cs)
public App()
{
InitializeComponent();
bool isLoggedIn = Current.Properties.ContainsKey("IsLoggedIn") ? Convert.ToBoolean(Current.Properties["IsLoggedIn"]) : false;
if (!isLoggedIn)
{
//Load if Not Logged In
MainPage = new NavigationPage(new MainPage());
}
else
{
//Load if Logged In
MainPage = new NavigationPage(new YourPageToLoadIfUserIsLoggedIn());
}
}
On Logout:
When you Logout, store the False
value in the IsLoggedIn
local storage key And clear the Navigation stack and Load the MainPage
.
Application.Current.Properties ["IsLoggedIn"] = Boolean.FalseString;
Storing User Detail:
To store the Settings class object values, serialize it into Json
(Nuget Package) string object and store it in some other key, say, UserDetail
in Application.Current.Properties
.
When you need this data back, fetch from local storage and deserailize it and use it.
Store : App.Current.Properties["UserDetail"] = JsonConvert.SerializeObject(Settings);
Retrieve : Settings userData = JsonConvert.DeserializeObject<Settings>(App.Current.Properties["UserDetail"]);
EDIT
Current.Properties.ContainsKey
just checks if some key exists in the storage or not. It doesn't check if value exists. Before accessing any key-value, its necessary to check if that key exists or not.
Static class can't be serialized, so you need to create a Singleton instance of that class and then access that singleton instance to serialize.
Hope this will help!!.
Upvotes: 10