How to show different pages when app launches time in windows phone 7? - windows-phone-7

When app launches time need to show the registration page.once user registered it shouldn't goes to registration page need to go log in page.
How to achieve this?

You can navigate to the start page of a Windows Phone app from code.
Remove the "DefaultTask" entry from the WMAppManifest
Remove the NavigationPage attribute from the "DefaultTask" in WMAppManifest, and in the Launching event of your app use the something like the example below to navigate to the page of choice upon launch.
private void Application_Launching(object sender, LaunchingEventArgs e)
{
if (registered)
{
((App)Application.Current).RootFrame.Navigate(new Uri("/<your start page>.xaml", UriKind.Relative));
}
else
{
((App)Application.Current).RootFrame.Navigate(new Uri("/<your registration page>.xaml", UriKind.Relative));
}
}
You just have to decide how you want to determine that someone already registered.

I guess you haven't put a lot of thought to this, the setup is pretty easy! When a user registers you could set a variable in the settings defining that a user already has registered. When the application starts, evaluate this setting and if the user registered you show the register-page, otherwise the login-page. Example:
//After (succesful) registration
Properties.Settings.Default.HasRegistered = true;
Properties.Settings.Default.Save();
//Check the value
var hasRegistered = Properties.Settings.Default.HasRegistered;
if(hasRegistered)
//show Login
else
//show Registration
You can also use the IsolatedStorageSettings.ApplcationSettings to do this. The code below is just sample code, you'll have to provide validation if the settings already exist on the first startup of the app and set a default value 'false' for the setting if no registration has occured yet.
//After registration
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("HasRegistered"))
settings["HasRegistered"] = true;
settings.Save();
//Check value
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("HasRegistered"))
{
var registered = bool.Parse(settings["HasRegistered"]);
if(registered)
//show login
else
//show registration
}
Hope this helps!

Related

Xamarin.Forms android check whether user clicked Deny and Don't ask again

In my xamarin.forms app. I am using xamarin.Essentials to check and request permissions. I can check whether a permission is granted or not in android. The problem I am facing is when user clicks "Deny and Don't ask again" the status still shows Denied. How can we know whether user selected Deny and Dont ask so that I can show a warning message according to that. Any help is appreciated.
For check and request permission in Xamarin.Forms you could also use the plugin Permission.Plugin from nuget .
The option Deny and Don't ask again will only appear when you deny the request the second time . However , there is no such a specific status to tag it .
As a workaround , we could define a custom property to save the time that we deny .
int DenyCount = 0;
private async void FabOnClick(object sender, EventArgs eventArgs)
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync<LocationPermission>();
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
{
//await DisplayAlert("Need location", "Gunna need that location", "OK");
DenyCount++;
if(DenyCount>=2)
{
//...
}
}
status = await CrossPermissions.Current.RequestPermissionAsync<LocationPermission>();
}
if (status == PermissionStatus.Granted)
{
//Query permission
DenyCount = 0; // reset the value of DenyCount
}
else if (status == PermissionStatus.Restricted)
{
//location denied
}
}
Xamarin.Essentials provides a method for detecting whether the user has clicked to "don't ask again". You can check if a dialog should be shown by calling ShouldShowRationale:
var canAskAgain = Xamarin.Essentials.Permissions.ShouldShowRationale<Permission_Type>();
var didCheckDontAskAgain = !canAskAgain;
If this is true, that means the user did not click "Deny and Don't Ask Again".
Also, note that on Android 12 (and maybe 11, not sure), if you click "Deny" mulitple times, Android assumes that you mean "Don't ask again". The user may never explicitly check that option, but it may be inferred by Android.

Cannot navigate to page which was called once before

Short intro into my application's-logic:
My application is using a REST-Api and needs a token for all requests but a specific one (let's call it "pairing-page").
Before I navigate to any of my pages I'm checking the target location. If my target is the page where I'm requesting the token, no checking for a existing token is made.
For every other page a token is necessary. If no token exists the user should navigate back to the "pairing-page".
My start-Page is my paring-page.
What's the problem?:
When starting the app (pairing-page) and getting the token and navigating to the 2nd page - let's call it "overview" - everything is ok. The overview has a button which calls a method that removes my token and navigates back to the pairing-page. That's working as well.
Now the interesting part:
When I try to pair & navigate to the overview again (2nd time), no navigation is done. By this I mean my overview is not popping up.
I'm using Xamarin's Shell Navigation and overriding the OnNavigating-Method.
Code:
protected override void OnNavigating(ShellNavigatingEventArgs args)
{
// check if BearerToken exist. If so, navigate to Overview
if (args.Target.Location.ToString() != "//Admission.Event.Pair"
&& args.Target.Location.ToString() != "Admission.Event.Pair")
{
App app = App.Current as App;
string bearerToken = RestServiceCalls.GetBearerToken(app._dependencyService);
// if a the token is missing call the Pairing-Page
if (string.IsNullOrEmpty(bearerToken)
|| string.IsNullOrWhiteSpace(bearerToken))
{
Device.BeginInvokeOnMainThread(async () => { await NavigateToPageAsync("Admission.Event.Pair"); });
return;
}
}
base.OnNavigating(args);
}
async Task NavigateToPageAsync(object pageName, bool animate = true)
{
await Xamarin.Forms.Shell.Current.GoToAsync($"{pageName.ToString()}", animate);
Xamarin.Forms.Shell.Current.FlyoutIsPresented = false;
}
Let's take a look into the args:
Application start, pairing-page:
args.Target.Location: //Admission.Event.Pair
args.Current.Location: null
The Pairing-Page is popping up, everything is ok.
Click on the Button which processes getting a token and after that navigating to the overview:
args.Target.Location: Admission.Event
args.Current.Location: //Admission.Event.Pair
The overview page is popping up, everything is ok. Got a valid token as well.
Click on Button which processes removing the token and navigating to the pairing-page:
args.Target.Location: Admission.Event.Pair
args.Current.Location: //Admission.Event.Pair/Admission.Event
The token is removed correctly (is null) and the pairing-page pops up. Everything is ok.
Now the problem occurs:
When I'm now trying to get a token and navigate to the overview again my args have this content and my overview wont show up:
args.Target.Location: Admission.Event
args.Current.Location: //Admission.Event.Pair/Admission.Event/Admission.Event.Pair
Any idea about that?
My first thought was it might be an issue with the target-location.
Like I said in my comment:
For me I could simple use:
if(shell != null){
INavigation navigation = shell.Navigation;
navigation.PopToRootAsync();
}

What is the best solution for "reseting" the Authentication stack?

Currently in my application I have two Navigation stacks.
Authentication
Main
My Authentication stack looks like this:
Splash Page
Choose Create or Login Page
Login Page
After that I call:
CoreMethods.SwitchOutRootNavigation(NavigationContext.Main);
This all works fine.
When I call Logout from within the Main stack like this:
CoreMethods.SwitchOutRootNavigation(NavigationContext.Authentication);
I will currently be on "Login Page", but I really want it to be the first page "Splash Page".
Having the Navigation stacks remember the stack history is perfect for all other cases.
Question: What is the best solution for "reseting" the Authentication stack?
What I normally do in my apps is following.
I have IAuthenticationService which has a State property, which can be LoggedIn or LoggedOut. When session state changed due to explicit login, or for instance token expires, I set the State to LoggedOut. Also I fire a broadcast message SessionStateChanged through Messenger, so I can catch this message all around the app, and react correspondingly in UI level, like change screen states and so on.
If need to completely log the user, I mean show login page when State is LoggedOut, which is your case, I do the following. I use Xamarin.Forms, but the approach would be similar if you use native iOS or Android.
In my main App class (the one which derives from Xamarin.Forms.Application) I create a method call UpdateMainPage, something like this
private async void UpdateMainPage()
{
if (_authService.State == SessionState.LoggedIn)
MainPage = new NavigationPage(new RequestPage());
else
MainPage = new NavigationPage(new SignInPage());
}
What happens I just change the root page of the application to SignIn flow or Main flow depending on SessionState. Then in my constructor I do the following.
public FormsApp()
{
InitializeComponent();
_authService = Mvx.Resolve<IAuthenticationService>();
UpdateMainPage();
var messenger = Mvx.Resolve<IMvxMessenger>();
_sessionStateChangedToken = messenger.Subscribe<SessionStateChangedMessage>(HandleSessionStateChanged);
}
What I need to do, I need to setup main page beforehand, then I subscribe to SessionStateChanged event, where I trigger UpdateMainPage
private void HandleSessionStateChanged(SessionStateChangedMessage sessionStateChangedMessage)
{
UpdateMainPage();
}
I used this approach for several apps, and it work perfect for me. Hope this helps
I had the very same problem recently and this is what I did:
Navigation stacks:
public enum NavigationStacks {Authentication, Main}
In the App.xaml.cs:
//Navigation stack when user is authenticated.
var mainPage = FreshPageModelResolver.ResolvePageModel<MainPageModel>();
var mainNavigation = new FreshNavigationContainer(MainPage, NavigationStacks.Main.ToString());
//Navigation stack for when user is not authenticated.
var splashScreenPage= FreshPageModelResolver.ResolvePageModel<SplashScreenPageModel>();
var authenticationNavigation = new FreshNavigationContainer(splashScreenPage, NavigationStacks.Authentication.ToString());
here you can leverage James Montemagno's Settings Plugin
if (Settings.IsUserLoggedIn)
{
MainPage = mainNavigation;
}
else
{
MainPage = authenticationNavigation;
}
So far you had already done the code above. But the idea for the problem is to clear the authentication stack except the root page i.e splash Screen:
public static void PopToStackRoot(NavigationStacks navigationStack)
{
switch (navigationStack)
{
case NavigationStacks.Authentication:
{
var mainPage = FreshPageModelResolver.ResolvePageModel<MainPageModel>();
var mainNavigation = new FreshNavigationContainer(MainPage, NavigationStacks.Main.ToString());
break;
}
case NavigationStacks.Main:
{
var splashScreenPage= FreshPageModelResolver.ResolvePageModel<SplashScreenPageModel>();
var authenticationNavigation = new FreshNavigationContainer(splashScreenPage, NavigationStacks.Authentication.ToString());
break;
}
}
}
And finally here is the code inside Logout command:
private void Logout()
{
Settings.IsUserLoggedIn = false;
NavigationService.PopToStackRoot(NavigationStacks.Authentication);
CoreMethods.SwitchOutRootNavigation(NavigationStacks.Authentication.ToString());
}
I know there may be better and more efficient approaches. But that worked for me.

Windows Phone MVVM Login Page design pattern?

I want to create a login page where the users enters username/password then a web service authenticates and saves an authentication token retrieved from the server.
I want the page view to be notified when the authentication is done successfully.
my question is: how to implement this in MVVM pattern ? I created a class for the model, a class for the model view and a class for the calling and parsing of the web service.
I can't set my ModelView as a DataContext for the page cause there are no controls that bind to the Model's data.
is this pattern an overkill or it can be implemented in another way ? please suggest.
Thanks
I have a login page that is implemented as described here. The login page itself does not have a viewmodel, but it does use a service that I wrote that contains a callback when the login completes. the service also contains other useful info about the user. I think MVVM would have been overkill here.
private void LoginButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(EmailTextBox.Text)) return;
if (string.IsNullOrEmpty(PasswordTextBox.Password)) return;
Login();
}
private void Login()
{
if (DeviceNetworkInformation.IsNetworkAvailable == false)
{
MessageBox.Show("I'm having trouble connecting to the internet." + Environment.NewLine + "Make sure you have cell service or are connected to WiFi then try again");
}
else
{
LoginButton.Focus(); // Removes the keyboard
UserProfile.Name = EmailTextBox.Text;
UserProfile.Password = PasswordTextBox.Password;
UserProfile.Current.Login(result =>
{
// callback could be on another thread
Dispatcher.BeginInvoke(() =>
{
// Did the login succeed?
if (result.Result)
{
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
else
{
string message = "Sorry, but I was not able to log in that user. Please make sure the name and password were entered correctly.";
MessageBox.Show(message, "Login failed");
}
});
});
}
}
You need to put ICommands in your ViewModel that point to methods who perform calls your web service, and the elements in your View should bind to those commands to perform actions.
And you need one more boolean property in your viewmodel: IsLoggedIn, that you set to true when the Login call to your webservice returns a success.
Then in your view, you can bind to IsLoggedIn to give feedback to your users.
Note: don't forget to raise PropertyChanged for IsLoggedIn in its setter.

Is it possible to check whether the location services are active?

is it possible to check whether the location services are active?
I mean Settings > Location > Location services
There is probably no direct API for calling, but could it work with the GeoCoordinateWatcher?
GeoCoordinateWatcher g = new GeoCoordinateWatcher();
g.Start();
if (g.Permission.Equals(GeoPositionPermission.Granted))
{
//Your location services is enabled. Go ahead.
//Your codes goes here.
}
else if (g.Permission.Equals(GeoPositionPermission.Denied) || g.Permission.Equals(GeoPositionPermission.Unknown))
{
MessageBox.Show("Location services are disabled. To enable them, Goto Settings - Location - Enable Location Services.", "Location services", MessageBoxButton.OK);
}
You can use the following code to determine the status of the Location service:
var watcher = new GeoCoordinateWatcher();
if (GeoPositionStatus.Disabled == watcher.Status)
{
// Watcher is disabled.
}
More realistically, you'll want to pay more attention to change to the status (just because the service isn't disabled doesn't mean you've got location data), so you shoudl take a look at the MSDN Documentation for working with the Location service.
There's also a good post on filtering and emulating location data using the Reactive extensions, which is perfect for that pre-device testing, though to save you time on that front the Widnows Phone Team have released the Windows Phone GPS Emulator.
Even with the started GeoCoordinateWatcher you will get NoData if the sensor is disabled. What you should try using instead is TryStart:
GeoCoordinateWatcher g = new GeoCoordinateWatcher();
MessageBox.Show(g.TryStart(false,TimeSpan.FromSeconds(30)).ToString());
If it returns False, it means that the sensor is disabled. If it returns True, it is enabled. Set an appropriate timeout period (in the snippet above I am using 30 seconds) and delegate this process to a secondary thread, so it won't hang the UI.
You can add a StatusChanged event to your GeoCoordinateWatcher and test for GeoPositionPermission.Denied in the permissions when it fires.
watcher = new GeoCoordinateWatcher();
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
watcher.Start();
void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
if (watcher.Permission == GeoPositionPermission.Denied)
{
// Location services were disabled
}
}
Hope that helps.
Made this one based on TeJ's answer.
public override void OnNavigatedTo()
{
using (var watcher = new GeoCoordinateWatcher())
{
try
{
watcher.Start();
}
finally
{
IsAllowedInSystem = watcher.Permission.Equals(GeoPositionPermission.Granted);
watcher.Stop();
}
}
}
And my apps' ToggleSwitch.IsEnabled is binded to IsAllowedInSystem.
When i'm switching to Location Service, disable it and return back to app, my ToggleSwitch is disabled (also a string "Please, enable Location Service in System settings" in visible). When i'm switching to Location Service, enable it and return back to my app, my ToggleSwitch is enabled and user can set it up.

Resources