0
votes

I have a problem with the hardware back button on windows phone 10 that does not work when the default page is the page BackgroundMusic.

App.cs

protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;
                rootFrame.Navigated += RootFrame_Navigated;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;

                // Register a handler for BackRequested events and set the  
                // visibility of the Back button  
                SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;

                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                    rootFrame.CanGoBack ?
                    AppViewBackButtonVisibility.Visible :
                    AppViewBackButtonVisibility.Collapsed;
            }

            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    rootFrame.Navigate(typeof(BackgroundMusic), e.Arguments);
                }
                // Ensure the current window is active
                Window.Current.Activate();
            }
        }

private void RootFrame_Navigated(object sender, NavigationEventArgs e)
        {
            // Each time a navigation event occurs, update the Back button's visibility  
            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                ((Frame)sender).CanGoBack ?
                AppViewBackButtonVisibility.Visible :
                AppViewBackButtonVisibility.Collapsed;
        }

        private void OnBackRequested(object sender, BackRequestedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            if (App.DetectPlatform() == Platform.WindowsPhone)
            {
                HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
                {
                    if (rootFrame.CanGoBack)
                    {

                        rootFrame.GoBack();
                        a.Handled = true;
                    }
                });
            }
            else if (App.DetectPlatform() == Platform.Windows)
            {
                if (rootFrame.CanGoBack)
                {
                    e.Handled = true;
                    rootFrame.GoBack();
                }
            }
        }

        public static Platform DetectPlatform()
        {
            bool isHardwareButtonsAPIPresent = ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");

            if (isHardwareButtonsAPIPresent)
            {
                return Platform.WindowsPhone;
            }
            else
            {
                return Platform.Windows;
            }
        }

public static MediaElement GlobalMediaElement
        {
            get { return Current.Resources["MyPlayer"] as MediaElement; }
        }

        private void mediaended(object sender, RoutedEventArgs e)
        {
            var AppMediaElement = App.GlobalMediaElement;
            AppMediaElement.Position = TimeSpan.Zero;
            AppMediaElement.Play();
        }

BackgroundMusic.cs

const string soundTrackToken = "soundtrack";
    int flag = 1;


    public BackgroundMusic()
    {
        this.InitializeComponent();
    }

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        //navigationHelper.OnNavigatedTo(e);
        mainFrame.Navigate(typeof(MainPage));

        if (StorageApplicationPermissions.FutureAccessList.ContainsItem(soundTrackToken))
        {
            StorageFile audioFile = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(soundTrackToken);
            if (audioFile != null)
            {
                await StartAudio(audioFile);
            }
        }
    }

How to handle it?

Note: - When the default page is MainPage, the hardware back button to work. But when the default page is the BackgroundMusic page, hardware back button does not work - BackgroundMusic page is a page for background music (there is also a play and stop button) on the application.

2

2 Answers

0
votes

Can you try this:

Under

SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;

put

HardwareButtons.BackPressed += OnBackRequested:

then delete this inside OnBackRequested

HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
            {

The explanation is that you need to register the event handler upfront. In your current code, you only handles software back button. When it is clicked and knowing that it is Phone platform, then you register a new event handler. So, what I suggested you to do is register the handler the same as the software back button up front, so it handles the same behavior, and you don't need to add new event handler if it is a phone later on.

0
votes

First of all, when on windows phone you handled hardware back button like this:

if (App.DetectPlatform() == Platform.WindowsPhone)
{
    HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
    {
        if (rootFrame.CanGoBack)
        {
            rootFrame.GoBack();
            a.Handled = true;
        }
    });
}

This is not right, it is like to handle the back button twice, two items in the BackStack of the rootFrame will be removed when back button is pressed on mobile. You can change this code like this:

if (App.DetectPlatform() == Platform.WindowsPhone)
{
    if (rootFrame.CanGoBack)
    {
        rootFrame.GoBack();
        e.Handled = true;
    }
}

Secondly, in the OnNavigatedTo event of your BackgroundMusic, I don't know what is your mainFrame, if this is the Frame inside the BackgroundMusic page, then it can be navigated to MainPage, the BackStack of rootFrame will have no items. And if this mainFrame is exactly the rootFrame, navigation will failed when it is on the OnNavigatedTo event, the items' count BackStack of rootFrame still remains to be 0.

So if you want to use rootFrame to navigate to MainPage when the default Page of rootFrame is BackgroundMusic, you can in the Loaded event navigate to MainPage for example like this:

private void BackgroundMusic_Loaded(object sender, RoutedEventArgs e)
{
    var status = this.Frame.Navigate(typeof(MainPage));
}