using Plugin.NFC; using System.Collections.ObjectModel; using System.Text; using System.Windows.Input; using System.Linq; namespace WorkFlowCheck.MAUI.Pages.NFC; public partial class NFCTestPage : ContentPage { public NFCTestPage() { InitializeComponent(); } public ObservableCollection NFCDataList { get; set; } public ICommand RefreshCommand { get; set; } public const string ALERT_TITLE = "NFC"; bool _eventsAlreadySubscribed = false; public bool IsRefreshing { get; set; } protected override async void OnAppearing() { base.OnAppearing(); CrossNFC.Legacy = false; if (CrossNFC.IsSupported) { if (!CrossNFC.Current.IsAvailable) await ShowAlert("NFC is not available"); if (!CrossNFC.Current.IsEnabled) await ShowAlert("NFC is disabled"); await AutoStartAsync().ConfigureAwait(false); } else { await ShowAlert("NFC is not available"); } RefreshCommand = new Command(async () => await LoadNFCDataList()); BindingContext = this; } Task ShowAlert(string message, string title = null) => DisplayAlert(string.IsNullOrWhiteSpace(title) ? ALERT_TITLE : title, message, "OK"); async Task AutoStartAsync() { // Some delay to prevent Java.Lang.IllegalStateException "Foreground dispatch can only be enabled when your activity is resumed" on Android await Task.Delay(500); await StartListeningIfNotiOS(); } async Task StartListeningIfNotiOS() { await BeginListening(); } async Task BeginListening() { try { MainThread.BeginInvokeOnMainThread(() => { SubscribeEvents(); CrossNFC.Current.StartListening(); }); } catch (Exception ex) { await ShowAlert(ex.Message); } } void SubscribeEvents() { if (_eventsAlreadySubscribed) UnsubscribeEvents(); _eventsAlreadySubscribed = true; CrossNFC.Current.OnMessageReceived += Current_OnMessageReceived_NFCData; //CrossNFC.Current.OnMessagePublished += Current_OnMessagePublished; //CrossNFC.Current.OnTagDiscovered += Current_OnTagDiscovered; //CrossNFC.Current.OnNfcStatusChanged += Current_OnNfcStatusChanged; //CrossNFC.Current.OnTagListeningStatusChanged += Current_OnTagListeningStatusChanged; } void UnsubscribeEvents() { CrossNFC.Current.OnMessageReceived -= Current_OnMessageReceived_NFCData; //CrossNFC.Current.OnMessagePublished -= Current_OnMessagePublished; //CrossNFC.Current.OnTagDiscovered -= Current_OnTagDiscovered; //CrossNFC.Current.OnNfcStatusChanged -= Current_OnNfcStatusChanged; //CrossNFC.Current.OnTagListeningStatusChanged -= Current_OnTagListeningStatusChanged; _eventsAlreadySubscribed = false; } async void Current_OnMessageReceived(ITagInfo tagInfo) { if (tagInfo == null) { await ShowAlert("No tag found"); return; } // Customized serial number var identifier = tagInfo.Identifier; var serialNumber = NFCUtils.ByteArrayToHexString(identifier, ":"); var title = !string.IsNullOrWhiteSpace(serialNumber) ? $"Tag [{serialNumber}]" : "Tag Info"; if (!tagInfo.IsSupported) { await ShowAlert("Unsupported tag (app)", title); } else if (tagInfo.IsEmpty) { await ShowAlert("Empty tag", title); } else { var first = tagInfo.Records[0]; await ShowAlert(GetMessage(first), title); } } async void Current_OnMessageReceived_NFCData(ITagInfo tagInfo) { if (tagInfo == null) { await ShowAlert("No tag found"); return; } // Customized serial number var identifier = tagInfo.Identifier; var serialNumber = NFCUtils.ByteArrayToHexString(identifier, ":"); if (NFCDataList == null) { NFCDataList = new ObservableCollection(); } NFCDataList.Add(new NFCData() { SerialNumber = serialNumber, DateReceived = $"{DateTime.Now.Date.ToShortDateString()} {DateTime.Now.ToLongTimeString()}" }); NFCDataListCollection.ItemsSource = NFCDataList.OrderByDescending(o => o.DateReceived); await LoadNFCDataList(); } private async Task LoadNFCDataList() { IsRefreshing = true; IsRefreshing = false; OnPropertyChanged(nameof(IsRefreshing)); OnPropertyChanged(nameof(NFCDataList)); } string GetMessage(NFCNdefRecord record) { var message = $"Message: {record.Message}"; message += Environment.NewLine; message += $"RawMessage: {Encoding.UTF8.GetString(record.Payload)}"; message += Environment.NewLine; message += $"Type: {record.TypeFormat}"; if (!string.IsNullOrWhiteSpace(record.MimeType)) { message += Environment.NewLine; message += $"MimeType: {record.MimeType}"; } return message; } protected override bool OnBackButtonPressed() { Shell.Current.GoToAsync("//MainPage"); return true; } }