NFC csak Androidra javítás ...

This commit is contained in:
2025-03-28 15:37:14 +01:00
parent 2341b186ef
commit b69f9af6f3
6 changed files with 142 additions and 213 deletions
@@ -4,6 +4,7 @@ using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.MAUI.Pages.BaseStock.CheckPoints; using WorkFlowCheck.MAUI.Pages.BaseStock.CheckPoints;
using WorkFlowCheck.MAUI.Services.Interfaces; using WorkFlowCheck.MAUI.Services.Interfaces;
using Plugin.NFC; using Plugin.NFC;
using WorkFlowCheck.MAUI.Pages.NFC;
namespace WorkFlowCheck.MAUI.Pages.BaseStock; namespace WorkFlowCheck.MAUI.Pages.BaseStock;
@@ -11,7 +12,7 @@ public partial class CheckPointsPage : ContentPage
{ {
private readonly IBaseStockService _baseStockService; private readonly IBaseStockService _baseStockService;
private readonly ISyncService _syncService; private readonly ISyncService _syncService;
private bool _onReceiveing = false;
public CheckPointsPage() public CheckPointsPage()
{ {
@@ -51,8 +52,20 @@ public partial class CheckPointsPage : ContentPage
} }
private async void OnPairItem(CheckPointDTO checkPointDTO) private async void OnPairItem(CheckPointDTO checkPointDTO)
{ {
_checkPointDTO = checkPointDTO; var checkPointCode = await NFCWaiter.ShowModalAsync();
await BeginListening(); if (!string.IsNullOrEmpty(checkPointCode))
{
if (Navigation.ModalStack.Count > 0)
{
await Navigation.PopModalAsync();
}
if (checkPointDTO != null)
{
checkPointDTO.Code = checkPointCode;
await _baseStockService.UpdateCheckPoint(checkPointDTO);
await LoadCheckPoints();
}
}
} }
protected override bool OnBackButtonPressed() protected override bool OnBackButtonPressed()
{ {
@@ -63,75 +76,4 @@ public partial class CheckPointsPage : ContentPage
{ {
_syncService.SyncCheckPointsUp(); _syncService.SyncCheckPointsUp();
} }
#region NFC
bool _eventsAlreadySubscribed = false;
CheckPointDTO _checkPointDTO = null;
async Task BeginListening()
{
try
{
MainThread.BeginInvokeOnMainThread(() =>
{
SubscribeEvents();
CrossNFC.Current.StartListening();
});
}
catch (Exception ex)
{
}
}
async Task EndListening()
{
try
{
MainThread.BeginInvokeOnMainThread(() =>
{
UnsubscribeEvents();
CrossNFC.Current.StopPublishing();
CrossNFC.Current.StopListening();
});
}
catch (Exception ex)
{
}
}
void SubscribeEvents()
{
if (_eventsAlreadySubscribed)
UnsubscribeEvents();
_eventsAlreadySubscribed = true;
CrossNFC.Current.OnMessageReceived += Current_OnMessageReceived_NFCData;
}
void UnsubscribeEvents()
{
CrossNFC.Current.OnMessageReceived -= Current_OnMessageReceived_NFCData;
_eventsAlreadySubscribed = false;
}
async void Current_OnMessageReceived_NFCData(ITagInfo tagInfo)
{
if (_onReceiveing) return;
_onReceiveing = true;
if (tagInfo == null)
{
return;
}
var identifier = tagInfo.Identifier;
var serialNumber = NFCUtils.ByteArrayToHexString(identifier, ":");
if (_checkPointDTO != null)
{
_checkPointDTO.Code = serialNumber;
await _baseStockService.UpdateCheckPoint(_checkPointDTO);
await Task.Delay(500);
await EndListening();
await LoadCheckPoints();
}
_onReceiveing = false;
}
#endregion
} }
@@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using WorkFlowCheck.Common.DTO; using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.MAUI.Pages.NFC; using WorkFlowCheck.MAUI.Pages.NFC;
@@ -55,16 +56,16 @@ public partial class CheckListPage : ContentPage
} }
private async void OnContinueItem(CheckListHeaderDTO checkListHeaderDTO) private async void OnContinueItem(CheckListHeaderDTO checkListHeaderDTO)
{ {
var taskCompletionSource = new TaskCompletionSource<string>(); var checkPointCode = await NFCWaiter.ShowModalAsync();
await Navigation.PushModalAsync(new NFCWaiter(taskCompletionSource)); if (!string.IsNullOrEmpty(checkPointCode))
var checkPintCode = await taskCompletionSource.Task; {
if (!string.IsNullOrEmpty(checkPintCode)) if (Navigation.ModalStack.Count > 0)
{ {
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
await Navigation.PushAsync(new CheckListWorkPage(checkListHeaderDTO.Id, checkPintCode));
} }
await Navigation.PushAsync(new CheckListWorkPage(checkListHeaderDTO.Id, checkPointCode));
}
} }
private async Task LoadCheckListTemplate() private async Task LoadCheckListTemplate()
{ {
@@ -2,11 +2,13 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WorkFlowCheck.MAUI.Pages.NFC.NFCWaiter" x:Class="WorkFlowCheck.MAUI.Pages.NFC.NFCWaiter"
Title="Várakozás NFC olvasásra"> Title="Várakozás NFC olvasásra"
<Grid HorizontalOptions="Center" VerticalOptions="Center"> BackgroundColor="Black">
<Label Grid.Row="0" <VerticalStackLayout Padding="20" HorizontalOptions="Center" VerticalOptions="Center">
Text="Várakozás az NFC beolvasásra ..." <Label Text="Tartsa a készülékhez az NFC tag-et..."
VerticalOptions="Center" TextColor="White"
FontSize="20"
HorizontalOptions="Center" /> HorizontalOptions="Center" />
</Grid> <ActivityIndicator IsRunning="True" Color="White" />
</VerticalStackLayout>
</ContentPage> </ContentPage>
@@ -1,132 +1,88 @@
using Plugin.NFC; using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace WorkFlowCheck.MAUI.Pages.NFC; namespace WorkFlowCheck.MAUI.Pages.NFC;
public partial class NFCWaiter : ContentPage public partial class NFCWaiter : ContentPage
{ {
private bool _nfcIsActive = false;
private TaskCompletionSource<string> _taskCompletionSource = new();
private bool _eventsAlreadySubscribed = false; public static async Task<string> ShowModalAsync()
private bool _onReceiveing = false; {
private TaskCompletionSource<string> _taskCompletionSource; var page = new NFCWaiter();
await Shell.Current.Navigation.PushModalAsync(page);
return await page._taskCompletionSource.Task;
}
public NFCWaiter(TaskCompletionSource<string> taskCompletionSource) public NFCWaiter()
{ {
InitializeComponent(); InitializeComponent();
_taskCompletionSource = taskCompletionSource;
} }
protected override async void OnAppearing() protected override async void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
#if ANDROID
CrossNFC.Legacy = false; if (Platform.CurrentActivity is Android.App.Activity activity && activity is MainActivity mainActivity)
if (CrossNFC.IsSupported)
{ {
if (!CrossNFC.Current.IsAvailable) mainActivity.StartNfc(OnTagRead);
await ShowAlert("NFC is not available"); _nfcIsActive = true;
if (!CrossNFC.Current.IsEnabled)
await ShowAlert("NFC is disabled");
await AutoStartAsync().ConfigureAwait(false);
} }
else #endif
{
await ShowAlert("NFC is not available");
}
}
protected override void OnDisappearing()
{
base.OnDisappearing();
}
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);
}
}
async Task StopListening()
{
try
{
MainThread.BeginInvokeOnMainThread(() =>
{
CrossNFC.Current.StopListening();
UnsubscribeEvents();
});
}
catch (Exception ex)
{
//await ShowAlert(ex.Message);
}
}
void SubscribeEvents()
{
if (_eventsAlreadySubscribed)
UnsubscribeEvents();
_eventsAlreadySubscribed = true;
CrossNFC.Current.OnMessageReceived += OnMessageReceived_NFCData;
}
void UnsubscribeEvents()
{
CrossNFC.Current.OnMessageReceived -= OnMessageReceived_NFCData;
_eventsAlreadySubscribed = false;
}
async void OnMessageReceived_NFCData(ITagInfo tagInfo)
{
_onReceiveing = true;
if (tagInfo == null)
{
await ShowAlert("No tag found");
_onReceiveing = false;
return;
}
// Customized serial number
var identifier = tagInfo.Identifier;
var serialNumber = NFCUtils.ByteArrayToHexString(identifier, ":");
_taskCompletionSource.TrySetResult(serialNumber);
_onReceiveing = false;
await Task.Delay(500);
await StopListening();
await MainThread.InvokeOnMainThreadAsync(async () => await MainThread.InvokeOnMainThreadAsync(async () =>
{ {
await Navigation.PopModalAsync(); await Task.Delay(TimeSpan.FromSeconds(30));
//await Navigation.PopModalAsync(); Finish(null);
}); });
} }
Task ShowAlert(string message, string title = null) => DisplayAlert(string.IsNullOrWhiteSpace(title) ? "NFC olvasás" : title, message, "OK");
protected override void OnDisappearing()
{
#if ANDROID
if (Platform.CurrentActivity is Android.App.Activity activity && activity is MainActivity mainActivity)
{
mainActivity.StopNfc();
}
#endif
base.OnDisappearing();
}
private void OnTagRead(string tagId)
{
Finish(tagId);
}
private async void Finish(string tagId)
{
#if ANDROID
if (Platform.CurrentActivity is Android.App.Activity activity && activity is MainActivity mainActivity)
{
if (_nfcIsActive)
{
mainActivity.StopNfc();
_nfcIsActive = false;
}
}
#endif
if (!_taskCompletionSource.Task.IsCompleted)
_taskCompletionSource.SetResult(tagId);
if (Navigation.ModalStack.Count > 0)
{
await Shell.Current.Navigation.PopModalAsync();
}
}
} }
@@ -10,5 +10,5 @@
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.nfc" android:required="false" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />
</manifest> </manifest>
@@ -1,40 +1,68 @@
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
using Android.Nfc;
using Android.OS; using Android.OS;
using Plugin.NFC;
namespace WorkFlowCheck.MAUI namespace WorkFlowCheck.MAUI
{ {
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity public class MainActivity : MauiAppCompatActivity
{ {
NfcAdapter nfcAdapter;
PendingIntent pendingIntent;
static Action<string> _onTagRead;
protected async override void OnDestroy() protected async override void OnDestroy()
{ {
SecureStorage.Default.Remove("WFCUser"); SecureStorage.Default.Remove("WFCUser");
SecureStorage.Default.Remove("AuthToken"); SecureStorage.Default.Remove("AuthToken");
base.OnDestroy(); base.OnDestroy();
} }
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
{ {
// Plugin NFC: Initialization before base.OnCreate(...) (Important on .NET MAUI)
CrossNFC.Init(this);
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
} nfcAdapter = NfcAdapter.GetDefaultAdapter(this);
protected override void OnResume() pendingIntent = PendingIntent.GetActivity(this, 0,
{ new Intent(this, typeof(MainActivity)).AddFlags(ActivityFlags.SingleTop),
base.OnResume(); Build.VERSION.SdkInt >= BuildVersionCodes.S ? PendingIntentFlags.Mutable : PendingIntentFlags.UpdateCurrent);
// Plugin NFC: Restart NFC listening on resume (needed for Android 10+)
CrossNFC.OnResume();
} }
protected override void OnNewIntent(Intent intent) protected override void OnNewIntent(Intent intent)
{ {
base.OnNewIntent(intent); base.OnNewIntent(intent);
// Plugin NFC: Tag Discovery Interception if (intent.Action == NfcAdapter.ActionTagDiscovered)
CrossNFC.OnNewIntent(intent); {
var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
var id = tag?.GetId();
if (id != null)
{
var hex = BitConverter.ToString(id).Replace("-", "");
_onTagRead?.Invoke(hex);
}
}
}
public void StartNfc(Action<string> onTagRead)
{
_onTagRead = onTagRead;
if (nfcAdapter.IsEnabled)
{
nfcAdapter?.EnableForegroundDispatch(this, pendingIntent, null, null);
}
}
public void StopNfc()
{
_onTagRead = null;
//if (!IsFinishing && !IsDestroyed)
//{
// nfcAdapter?.DisableForegroundDispatch(this);
//}
} }
} }
} }