Plugin.NFC icon indicating copy to clipboard operation
Plugin.NFC copied to clipboard

Wrong behavior with Navigation

Open EvilKingStone opened this issue 5 years ago • 13 comments

I use navigation in my xamarin.forms app and "OnAppearing" calling again when tag is detected by device. And I get 'Tag is missing' when try to write tag. Everything will be ok in singlepage application.

To reproduce error you can change App.xaml.cs in your sample: MainPage = new NavigationPage(new MainPage()); and try to write tag

EvilKingStone avatar Apr 26 '20 11:04 EvilKingStone

You probably have to subscribe on NFC events elsewhere than OnAppearing. A quick fix for the sample will be like this:

bool _eventsAlreadySubscribed = false;
void SubscribeEvents()
{
    if (_eventsAlreadySubscribed)
        return;
    _eventsAlreadySubscribed = true;

    CrossNFC.Current.OnMessageReceived += Current_OnMessageReceived;
    [...]
}

franckbour avatar May 17 '20 10:05 franckbour

It doesn't matter where the subscription is done.

  1. Create blank Xamarin Forms Project.
  2. Init CrossNFC in Android project, set required permissions.
  3. Change in the shared project app.xaml.cs Main page to the navigation page
        public App()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new MainPage());
        }
  1. Add button to the MainPage. Bind to ListenCommand
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="Catyari.Xam.Nfc.Mobile.MainPage">

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />

        <Button Text="Listen" Command="{Binding ListenCommand}"/>
    </StackLayout>

</ContentPage>
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            this.ListenCommand = new Command(() => 
            {
                CrossNFC.Current.StartListening();
                CrossNFC.Current.OnMessageReceived += this.OnNfcMessage;
            });
            this.BindingContext = this;

            InitializeComponent();
        }

        private void OnNfcMessage(ITagInfo tagInfo)
        {
        }

        public ICommand ListenCommand { get; }


        protected override void OnAppearing()
        {
            base.OnAppearing(); // set breakpoint here
        }
    }
  1. Run app
  2. Set breakpoint in OnAppearing method.
  3. Click Listen button.
  4. Place card on phone NFC sensor.

Current result: app stops on the breakpoint in OnAppearing method

dm-CaT avatar Jun 01 '20 16:06 dm-CaT

I did some googling about that. The reason is that the MainActivity is paused before new intent processing.

dm-CaT avatar Jun 01 '20 17:06 dm-CaT

The only one way I found to avoid it is to push page in modal navigation stack. This case OnAppearing is not called.

dm-CaT avatar Jun 01 '20 18:06 dm-CaT

I'm also encountering this issue. OnDisappearing() is called before the event is handled and OnAppearing() is called after the event is handled. @dm-CaT did you find any other way around it?

timothy-gibson avatar Jun 03 '20 11:06 timothy-gibson

@dm-CaT, @timothy-gibson

  1. Create blank Xamarin Forms Project.
  2. Init CrossNFC in Android project, set required permissions.
  3. Change in the shared project app.xaml.cs Main page to the navigation page
  4. Add button to the MainPage. Bind to ListenCommand
  5. Run app
  6. Set breakpoint in OnAppearing method.
  7. Click Listen button.
  8. Place card on phone NFC sensor.

Current result: app stops on the breakpoint in OnAppearing method

I followed these reproduction steps but I didn't reproduce the final result, app didn't stop. This is my test project: TestIssue27.zip

But I maybe misunderstood the issue... If so, please provide a reproduction sample and some clear explanations.

franckbour avatar Jun 03 '20 16:06 franckbour

@franckbour, I took your test project and the issue is reproduced. Here is video with your project: youtube

The problem is when you read a NFC card the page in non-modal navigation stack disappears and appears (OnDisapearing and OnAppearing are called). OnAppearing method is used primarily to load some data. And loading occurs every time when a NFC is read.

dm-CaT avatar Jun 03 '20 17:06 dm-CaT

@timothy-gibson,

@dm-CaT did you find any other way around it?

No, I didn't. To way around I took a look into Xamarin Forms source code. I was looking for a place where OnDisappearing/OnAppearing are called as the result of the MainActivity deactivation and activation back. But I didn't find such code because XF source code is too entangled. I think if we'll find this piece of code we'll be able avoid somehow OnAppearing/OnDesappearing calls.

dm-CaT avatar Jun 03 '20 17:06 dm-CaT

@dm-CaT and @timothy-gibson I made it work in my ViewModel perfectly in a stable app. All i did was ensure that I assigned the event handlers only once, and then in the destructor of the viewmodel, and every navigation away from the page, i unassigned the event handlers

saamerm avatar Jul 12 '20 21:07 saamerm

Hi @saamerm I am stuck with this issue. Can you explain how do you workaround it? I didn't understand your last message. Thanks.

pazunino avatar Dec 22 '20 22:12 pazunino

@pazunino if you see @dm-CaT ‘s comment, you cannot reliably use the OnAppearing and OnDisappearing from Android. So instead try to use a view model and use the constructor and destructor of the view model instead

saamerm avatar Dec 23 '20 02:12 saamerm

Is any progress with this issue? I think that this issue limited the usage of NFC in Xamarin.Forms. I tested with AppShell and the same problem occurred.

Senso4sLab avatar Jun 06 '21 06:06 Senso4sLab

I use another workaround for my MAUI application. In the OnAppearing() and OnDisappearing() functions, I directly return when the application is not navigating between pages (called when NFC is used). In AppShell.xaml.cs, I set a static bool to true in the function OnNavigating(ShellNavigatingEventArgs args). After in All OnAppearing(), I test this bool to directly return or to set it to false and execute all lines in OnAppearing(). In All OnDisappearing() I test this bool to directly return or execute all lines. So with a card on phone NFC, the 2 functions OnAppearing() and OnDisappearing() are called but there is a return.

This is the MAUI sample code tested in Android: Plugin.NFCWorkaround.zip

image

image

AlanGusLive avatar Aug 25 '22 14:08 AlanGusLive