How to set Main Page (or wait for MainThread) if app is closed during the startup process.

JasonTomsJasonToms USMember ✭✭
edited November 2016 in Xamarin.Forms

When my app is launched, a splash screen is set which is just an ActivityIndicator. Then, a task is run that starts up services and looks for saved passwords. This task is run async so the ActivityIndicator can spin. This works ok unless the home button (Android) is pressed while this task is running. I know it is because if the app is closed, the main thread is not accessible. But what I do not know is how I could solve this. I will post App.xaml.cs below.

        public App()
        {
            InitializeComponent();

            MainPage = new SplashScreen();

            app = this;
        }

        protected override async void OnStart()
        {
            base.OnStart();
            await StartupAsync();
        }

        private async Task StartupAsync()
        {
            ServiceRegistrator.Startup();

            MessagingCenter.Subscribe<NavigationMenuMasterDetailPage>(this, MessagingServiceConstants.LOGOUT, (sender) =>
            {
                Logout();
            });

            var assemblyType = typeof(App).GetTypeInfo();

            AutoFac.Builder.RegisterAssemblyTypes(assemblyType.Assembly)
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces()
                .SingleInstance();

            _keyChainHelper = AutoFac.Container.Resolve<IKeyChainHelper>();

            TextResources.Culture = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();

            var hasCredentials = HasKeyInChainstore("username") && HasKeyInChainstore("password");

            if (hasCredentials)
            {
                await Task.Run(() =>
                {
                    var logonService = AutoFac.Container.Resolve<ILogonService>();
                    var username = _keyChainHelper.GetKey("username");
                    var password = _keyChainHelper.GetKey("password");
                    logonService.Logon(username, password);
                });

                Device.BeginInvokeOnMainThread(() =>
                {
                    MainPage = new NavigationMenuMasterDetailPage();
                });
            }
            else
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    ShowLoginPage();
                });
            }
        }

I know there must be something to do to either wait for the main thread to be available, or force the app to open again. The exact exception is "java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState" and this occurs at the Device.BeginInvokeOnMainThread().

Sign In or Register to comment.