diff --git a/NFCLockDemoV2.sln b/NFCLockDemoV2.sln
new file mode 100644
index 0000000..96d46ff
--- /dev/null
+++ b/NFCLockDemoV2.sln
@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36429.23 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFCLockDemoV2", "NFCLockDemoV2\NFCLockDemoV2.csproj", "{A15D24B1-BE68-486F-B41B-21353FDD0B0F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidBinding1", "AndroidBinding1\AndroidBinding1.csproj", "{60D96270-D39B-4D6B-9DE5-DC666949D9F5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A15D24B1-BE68-486F-B41B-21353FDD0B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A15D24B1-BE68-486F-B41B-21353FDD0B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A15D24B1-BE68-486F-B41B-21353FDD0B0F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {A15D24B1-BE68-486F-B41B-21353FDD0B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A15D24B1-BE68-486F-B41B-21353FDD0B0F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {60D96270-D39B-4D6B-9DE5-DC666949D9F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {60D96270-D39B-4D6B-9DE5-DC666949D9F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {60D96270-D39B-4D6B-9DE5-DC666949D9F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {60D96270-D39B-4D6B-9DE5-DC666949D9F5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FC10FDEE-78D8-4C0D-B78D-5E8BA691ED91}
+ EndGlobalSection
+EndGlobal
diff --git a/NFCLockDemoV2/App.xaml b/NFCLockDemoV2/App.xaml
new file mode 100644
index 0000000..730fb6b
--- /dev/null
+++ b/NFCLockDemoV2/App.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/App.xaml.cs b/NFCLockDemoV2/App.xaml.cs
new file mode 100644
index 0000000..a2bbda1
--- /dev/null
+++ b/NFCLockDemoV2/App.xaml.cs
@@ -0,0 +1,15 @@
+namespace NFCLockDemoV2
+{
+ public partial class App : Application
+ {
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override Window CreateWindow(IActivationState? activationState)
+ {
+ return new Window(new AppShell());
+ }
+ }
+}
\ No newline at end of file
diff --git a/NFCLockDemoV2/AppShell.xaml b/NFCLockDemoV2/AppShell.xaml
new file mode 100644
index 0000000..e7bf1df
--- /dev/null
+++ b/NFCLockDemoV2/AppShell.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/AppShell.xaml.cs b/NFCLockDemoV2/AppShell.xaml.cs
new file mode 100644
index 0000000..179905a
--- /dev/null
+++ b/NFCLockDemoV2/AppShell.xaml.cs
@@ -0,0 +1,10 @@
+namespace NFCLockDemoV2
+{
+ public partial class AppShell : Shell
+ {
+ public AppShell()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/NFCLockDemoV2/Converters/OperationColorConverter.cs b/NFCLockDemoV2/Converters/OperationColorConverter.cs
new file mode 100644
index 0000000..f64e6ab
--- /dev/null
+++ b/NFCLockDemoV2/Converters/OperationColorConverter.cs
@@ -0,0 +1,26 @@
+using System.Globalization;
+using NFCLockDemoV2.ViewModels;
+
+namespace NFCLockDemoV2.Converters;
+
+public class OperationColorConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is OperationType currentOperation && parameter is string operationStr)
+ {
+ if (Enum.TryParse(operationStr, out var targetOperation))
+ {
+ return currentOperation == targetOperation
+ ? Color.FromArgb("#00BCD4") // Cyan
+ : Color.FromArgb("#D3D3D3"); // LightGray
+ }
+ }
+ return Color.FromArgb("#D3D3D3");
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/NFCLockDemoV2/Converters/PercentageConverter.cs b/NFCLockDemoV2/Converters/PercentageConverter.cs
new file mode 100644
index 0000000..e7c0a70
--- /dev/null
+++ b/NFCLockDemoV2/Converters/PercentageConverter.cs
@@ -0,0 +1,24 @@
+using System.Globalization;
+
+namespace NFCLockDemoV2.Converters;
+
+public class PercentageConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is int progress)
+ {
+ return progress / 100.0;
+ }
+ return 0.0;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double progress)
+ {
+ return (int)(progress * 100);
+ }
+ return 0;
+ }
+}
diff --git a/NFCLockDemoV2/GlobalXmlns.cs b/NFCLockDemoV2/GlobalXmlns.cs
new file mode 100644
index 0000000..3ee841f
--- /dev/null
+++ b/NFCLockDemoV2/GlobalXmlns.cs
@@ -0,0 +1,2 @@
+[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/maui/global", "NFCLockDemoV2")]
+[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/maui/global", "NFCLockDemoV2.Pages")]
diff --git a/NFCLockDemoV2/MainPage.xaml b/NFCLockDemoV2/MainPage.xaml
new file mode 100644
index 0000000..077f61e
--- /dev/null
+++ b/NFCLockDemoV2/MainPage.xaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/MainPage.xaml.cs b/NFCLockDemoV2/MainPage.xaml.cs
new file mode 100644
index 0000000..ee96579
--- /dev/null
+++ b/NFCLockDemoV2/MainPage.xaml.cs
@@ -0,0 +1,15 @@
+using NFCLockDemoV2.ViewModels;
+
+namespace NFCLockDemoV2;
+
+public partial class MainPage : ContentPage
+{
+ private MainViewModel _mainMainViewModel;
+
+ public MainPage(MainViewModel mainViewModel)
+ {
+ InitializeComponent();
+ _mainMainViewModel = mainViewModel;
+ BindingContext = _mainMainViewModel;
+ }
+}
\ No newline at end of file
diff --git a/NFCLockDemoV2/MauiProgram.cs b/NFCLockDemoV2/MauiProgram.cs
new file mode 100644
index 0000000..50af6e8
--- /dev/null
+++ b/NFCLockDemoV2/MauiProgram.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.Logging;
+using NFCLockDemoV2.ViewModels;
+
+namespace NFCLockDemoV2
+{
+ public static class MauiProgram
+ {
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+ builder.Services.AddSingleton();
+ return builder.Build();
+ }
+ }
+}
diff --git a/NFCLockDemoV2/NFCLockDemoV2.csproj b/NFCLockDemoV2/NFCLockDemoV2.csproj
new file mode 100644
index 0000000..4fdbd1a
--- /dev/null
+++ b/NFCLockDemoV2/NFCLockDemoV2.csproj
@@ -0,0 +1,113 @@
+
+
+
+ net9.0-android;net9.0-ios;net9.0-maccatalyst
+ $(TargetFrameworks);net9.0-windows10.0.19041.0
+
+
+
+
+
+
+ Exe
+ NFCLockDemoV2
+ true
+ true
+ enable
+ enable
+
+
+ NFCLockDemoV2
+
+
+ com.elitesys.nfclockdemov2
+
+
+ 1.0
+ 1
+
+
+ None
+
+ 15.0
+ 15.0
+ 30.0
+ 10.0.17763.0
+ 10.0.17763.0
+ 6.5
+
+
+
+ apk
+ False
+ com.elitesys.nfclockdemov2
+
+
+
+ False
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+ com.elitesys.nfclockdemov2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/Platforms/Android/AndroidManifest.xml b/NFCLockDemoV2/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 0000000..1048cc4
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Platforms/Android/MainActivity.cs b/NFCLockDemoV2/Platforms/Android/MainActivity.cs
new file mode 100644
index 0000000..395ec6b
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Android/MainActivity.cs
@@ -0,0 +1,89 @@
+using Android.App;
+using Android.Content;
+using Android.Content.PM;
+using Android.Nfc;
+using Android.Nfc.Tech;
+using Android.OS;
+using Com.Lvcheng.Lock.Shared.Nfc.Example.Java;
+using NFCLockDemoV2;
+using NFCLockDemoV2.Platforms.Android;
+using NFCLockDemoV2.ViewModels;
+using Microsoft.Maui;
+using Microsoft.Maui.Controls;
+
+namespace NFCLockAppV2;
+
+[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density, Exported = true)]
+[IntentFilter(new[] { Intent.ActionMain }, Categories = new[] { Intent.CategoryLauncher })]
+[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
+public class MainActivity : MauiAppCompatActivity
+{
+ private NFCHelper? nfcHelper;
+ private MainViewModel mainViewModel;
+ /*private NfcAdapter? nfcAdapter;
+ private PendingIntent? pendingIntent;
+ private IntentFilter[]? intentFilters = [];
+ private string[][] techLict = new string[1][] { [typeof(NfcA).FullName] };*/
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ base.OnCreate(savedInstanceState);
+ // 初始化 NFC Helper
+ InitializeNFC();
+ /*nfcAdapter = NfcAdapter.GetDefaultAdapter(this);
+ pendingIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)).AddFlags(ActivityFlags.ReceiverReplacePending), PendingIntentFlags.Mutable); */
+ }
+
+ private void InitializeNFC()
+ {
+ if (!TryInitializeNFC())
+ {
+ // 延迟到UI线程完全准备好后再尝试
+ Microsoft.Maui.Controls.Application.Current.Dispatcher.Dispatch(() =>
+ {
+ TryInitializeNFC();
+ });
+ }
+ }
+
+ private bool TryInitializeNFC()
+ {
+ if (nfcHelper != null && mainViewModel != null)
+ return true;
+
+ MainViewModel viewModel = null;
+ if (Microsoft.Maui.Controls.Application.Current?.Handler?.MauiContext?.Services != null)
+ {
+ viewModel = Microsoft.Maui.Controls.Application.Current.Handler.MauiContext.Services.GetService();
+ }
+
+ if (viewModel != null)
+ {
+ NFCCallbacks nFCCallbacks = new NFCCallbacks(viewModel);
+ nfcHelper = new NFCHelper(this, nFCCallbacks);
+ return true;
+ }
+
+ return false;
+ }
+
+ protected override void OnResume()
+ {
+ base.OnResume();
+ // 确保NFC功能在每次恢复时都已初始化
+ InitializeNFC();
+ nfcHelper.OnResume();
+ }
+
+ protected override void OnPause()
+ {
+ base.OnPause();
+ nfcHelper.OnPause();
+ }
+
+ protected override void OnNewIntent(Intent intent)
+ {
+ base.OnNewIntent(intent);
+ nfcHelper.OnNewIntent(intent);
+ }
+}
\ No newline at end of file
diff --git a/NFCLockDemoV2/Platforms/Android/MainApplication.cs b/NFCLockDemoV2/Platforms/Android/MainApplication.cs
new file mode 100644
index 0000000..0160d52
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Android/MainApplication.cs
@@ -0,0 +1,16 @@
+using Android.App;
+using Android.Runtime;
+
+namespace NFCLockDemoV2
+{
+ [Application]
+ public class MainApplication : MauiApplication
+ {
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/Android/NFCCallbacks.cs b/NFCLockDemoV2/Platforms/Android/NFCCallbacks.cs
new file mode 100644
index 0000000..ff72e1f
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Android/NFCCallbacks.cs
@@ -0,0 +1,178 @@
+using Java.Lang;
+using Com.Lvcheng.Lock.Shared.Nfc.Example.Java;
+using NFCLockDemoV2.ViewModels;
+using Android.Util;
+using Exception = System.Exception;
+using Microsoft.Maui.ApplicationModel;
+
+namespace NFCLockDemoV2.Platforms.Android
+{
+ public class NFCCallbacks : Java.Lang.Object, INFCCallbacks
+ {
+ private readonly MainViewModel mainViewModel;
+ private ViewModels.OperationType? operation => mainViewModel.Operation;
+ public NFCCallbacks(MainViewModel mainViewModel)
+ {
+ this.mainViewModel = mainViewModel;
+ }
+
+ public void OnFinished()
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.DeviceId = "--";
+ mainViewModel.DeviceRssi = "--";
+ mainViewModel.DeviceStatus = "NFC操作完成";
+ mainViewModel.Operation = null;
+ mainViewModel.ArcProgress = 0;
+ });
+ }
+
+ public Java.Lang.Boolean? OnLoop(DeviceManagerWrapper? wrapper, Long? id, Java.Lang.Boolean? isNew, Integer? rssi)
+ {
+ try
+ {
+ // 在主线程上更新UI
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ // 更新设备信息
+ mainViewModel.DeviceId = id?.ToString() ?? "--";
+ mainViewModel.DeviceRssi = rssi?.ToString() ?? "--";
+ });
+
+ string password = mainViewModel.Password;
+
+ // 开关锁需要先充电
+ if (operation == ViewModels.OperationType.LOCK || operation == ViewModels.OperationType.UNLOCK)
+ {
+ while (true)
+ {
+ Com.Lvcheng.Lock.Shared.Nfc.Result result = wrapper.GetChargeLevel(password);
+ if (result == Com.Lvcheng.Lock.Shared.Nfc.Result.Ok)
+ {
+ Integer? level = wrapper.MGetChargeLevel();
+ string levelText = level?.ToString() ?? "0";
+
+ // 在主线程上更新UI
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("充电中(" + levelText + "%)");
+
+ // 更新进度条
+ if (level != null)
+ {
+ mainViewModel.ArcProgress = level.IntValue();
+ }
+ });
+
+ if (level != null && level.IntValue() >= 100)
+ {
+ break;
+ }
+ }
+ else if (result == Com.Lvcheng.Lock.Shared.Nfc.Result.Unauthorized)
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("验证失败");
+ });
+ // 返回 false 手动结束 NFC 连接
+ return new Java.Lang.Boolean(false);
+ }
+ else
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("充电失败");
+ });
+ return new Java.Lang.Boolean(false);
+ }
+
+ // 添加短暂延迟以避免过度频繁的循环
+ System.Threading.Thread.Sleep(100);
+ }
+ }
+
+ if (operation != null)
+ {
+ switch (operation)
+ {
+ case ViewModels.OperationType.UNLOCK:
+ if (wrapper.Control(password, false) == Com.Lvcheng.Lock.Shared.Nfc.Result.Ok)
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("开锁成功");
+ });
+ }
+ else
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("开锁失败");
+ });
+ }
+ return new Java.Lang.Boolean(false);
+
+ case ViewModels.OperationType.LOCK:
+ if (wrapper.Control(password, true) == Com.Lvcheng.Lock.Shared.Nfc.Result.Ok)
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("关锁成功");
+ });
+ }
+ else
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("关锁失败");
+ });
+ }
+ return new Java.Lang.Boolean(false);
+
+ case ViewModels.OperationType.SET_PASSWORD:
+ if (wrapper.SetKey(password, "") == Com.Lvcheng.Lock.Shared.Nfc.Result.Ok)
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("设置密码成功");
+ });
+ }
+ else
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("设置密码失败");
+ });
+ }
+ return new Java.Lang.Boolean(false);
+ }
+ }
+
+ return new Java.Lang.Boolean(true);
+ }
+ catch (Exception ex)
+ {
+ Log.Error("NFCCallbacks", "Error in OnLoop: " + ex.Message);
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.UpdateMessage("操作异常: " + ex.Message);
+ });
+ return new Java.Lang.Boolean(false);
+ }
+ }
+
+ public void OnLost()
+ {
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ mainViewModel.DeviceId = "--";
+ mainViewModel.DeviceRssi = "--";
+ mainViewModel.DeviceStatus = "设备连接断开";
+ mainViewModel.Operation = null;
+ mainViewModel.ArcProgress = 0;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/NFCLockDemoV2/Platforms/Android/Resources/values/colors.xml b/NFCLockDemoV2/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 0000000..c04d749
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Platforms/MacCatalyst/AppDelegate.cs b/NFCLockDemoV2/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 0000000..e8983da
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace NFCLockDemoV2
+{
+ [Register("AppDelegate")]
+ public class AppDelegate : MauiUIApplicationDelegate
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/MacCatalyst/Entitlements.plist b/NFCLockDemoV2/Platforms/MacCatalyst/Entitlements.plist
new file mode 100644
index 0000000..de4adc9
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/MacCatalyst/Entitlements.plist
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+ com.apple.security.network.client
+
+
+
+
diff --git a/NFCLockDemoV2/Platforms/MacCatalyst/Info.plist b/NFCLockDemoV2/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 0000000..7268977
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UIDeviceFamily
+
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/NFCLockDemoV2/Platforms/MacCatalyst/Program.cs b/NFCLockDemoV2/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 0000000..47f8971
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace NFCLockDemoV2
+{
+ public class Program
+ {
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/Tizen/Main.cs b/NFCLockDemoV2/Platforms/Tizen/Main.cs
new file mode 100644
index 0000000..79456d7
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Tizen/Main.cs
@@ -0,0 +1,17 @@
+using System;
+using Microsoft.Maui;
+using Microsoft.Maui.Hosting;
+
+namespace NFCLockDemoV2
+{
+ internal class Program : MauiApplication
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/Tizen/tizen-manifest.xml b/NFCLockDemoV2/Platforms/Tizen/tizen-manifest.xml
new file mode 100644
index 0000000..6d26227
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Tizen/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ maui-appicon-placeholder
+
+
+
+
+ http://tizen.org/privilege/internet
+
+
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Platforms/Windows/App.xaml b/NFCLockDemoV2/Platforms/Windows/App.xaml
new file mode 100644
index 0000000..f67e14e
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/NFCLockDemoV2/Platforms/Windows/App.xaml.cs b/NFCLockDemoV2/Platforms/Windows/App.xaml.cs
new file mode 100644
index 0000000..f713719
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,25 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace NFCLockDemoV2.WinUI
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public partial class App : MauiWinUIApplication
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+
+}
diff --git a/NFCLockDemoV2/Platforms/Windows/Package.appxmanifest b/NFCLockDemoV2/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 0000000..24ce633
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/Platforms/Windows/app.manifest b/NFCLockDemoV2/Platforms/Windows/app.manifest
new file mode 100644
index 0000000..cbcb872
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/Windows/app.manifest
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
diff --git a/NFCLockDemoV2/Platforms/iOS/AppDelegate.cs b/NFCLockDemoV2/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 0000000..e8983da
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace NFCLockDemoV2
+{
+ [Register("AppDelegate")]
+ public class AppDelegate : MauiUIApplicationDelegate
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/iOS/Info.plist b/NFCLockDemoV2/Platforms/iOS/Info.plist
new file mode 100644
index 0000000..0004a4f
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/iOS/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/NFCLockDemoV2/Platforms/iOS/Program.cs b/NFCLockDemoV2/Platforms/iOS/Program.cs
new file mode 100644
index 0000000..47f8971
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/iOS/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace NFCLockDemoV2
+{
+ public class Program
+ {
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+ }
+}
diff --git a/NFCLockDemoV2/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/NFCLockDemoV2/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000..24ab3b4
--- /dev/null
+++ b/NFCLockDemoV2/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
@@ -0,0 +1,51 @@
+
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryFileTimestamp
+ NSPrivacyAccessedAPITypeReasons
+
+ C617.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategorySystemBootTime
+ NSPrivacyAccessedAPITypeReasons
+
+ 35F9.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryDiskSpace
+ NSPrivacyAccessedAPITypeReasons
+
+ E174.1
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/Resources/AppIcon/appicon.svg b/NFCLockDemoV2/Resources/AppIcon/appicon.svg
new file mode 100644
index 0000000..9d63b65
--- /dev/null
+++ b/NFCLockDemoV2/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Resources/AppIcon/appiconfg.svg b/NFCLockDemoV2/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/NFCLockDemoV2/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Resources/Fonts/OpenSans-Regular.ttf b/NFCLockDemoV2/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000..1beddae
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Fonts/OpenSans-Regular.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:037236ed4bf58a85f67074c165d308260fd6be01c86d7df4e79ea16eb273f8c5
+size 96932
diff --git a/NFCLockDemoV2/Resources/Fonts/OpenSans-Semibold.ttf b/NFCLockDemoV2/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 0000000..d81c625
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Fonts/OpenSans-Semibold.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e8d9e1a89083cd1b0849993fe2f3acc9aa33b7f439f7e8616872f6897f30684
+size 100820
diff --git a/NFCLockDemoV2/Resources/Images/dotnet_bot.png b/NFCLockDemoV2/Resources/Images/dotnet_bot.png
new file mode 100644
index 0000000..f7908fa
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Images/dotnet_bot.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:73e18a374cfd96ee54f8d7b7b0bf511d94e86e2f82caa36b226ffb2139363301
+size 93437
diff --git a/NFCLockDemoV2/Resources/Raw/AboutAssets.txt b/NFCLockDemoV2/Resources/Raw/AboutAssets.txt
new file mode 100644
index 0000000..89dc758
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with your package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/NFCLockDemoV2/Resources/Splash/splash.svg b/NFCLockDemoV2/Resources/Splash/splash.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Resources/Styles/Colors.xaml b/NFCLockDemoV2/Resources/Styles/Colors.xaml
new file mode 100644
index 0000000..30307a5
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Styles/Colors.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ #512BD4
+ #ac99ea
+ #242424
+ #DFD8F7
+ #9880e5
+ #2B0B98
+
+ White
+ Black
+ #D600AA
+ #190649
+ #1f1f1f
+
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NFCLockDemoV2/Resources/Styles/Styles.xaml b/NFCLockDemoV2/Resources/Styles/Styles.xaml
new file mode 100644
index 0000000..fdb0cd7
--- /dev/null
+++ b/NFCLockDemoV2/Resources/Styles/Styles.xaml
@@ -0,0 +1,444 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFCLockDemoV2/ViewModels/MainViewModel.cs b/NFCLockDemoV2/ViewModels/MainViewModel.cs
new file mode 100644
index 0000000..c2f14b4
--- /dev/null
+++ b/NFCLockDemoV2/ViewModels/MainViewModel.cs
@@ -0,0 +1,81 @@
+using System.Windows.Input;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+namespace NFCLockDemoV2.ViewModels;
+
+public class MainViewModel : ObservableObject
+{
+ private ViewModels.OperationType? _operation;
+ public ViewModels.OperationType? Operation
+ {
+ get => _operation;
+ set => SetProperty(ref _operation, value);
+ }
+
+ private int _arcProgress;
+ public int ArcProgress
+ {
+ get => _arcProgress;
+ set => SetProperty(ref _arcProgress, value);
+ }
+
+ private string _deviceId = "--";
+ public string DeviceId
+ {
+ get => _deviceId;
+ set => SetProperty(ref _deviceId, value);
+ }
+
+ private string _deviceStatus = "";
+ public string DeviceStatus
+ {
+ get => _deviceStatus;
+ set => SetProperty(ref _deviceStatus, value);
+ }
+
+ private string _deviceRssi = "--";
+ public string DeviceRssi
+ {
+ get => _deviceRssi;
+ set => SetProperty(ref _deviceRssi, value);
+ }
+
+ private string _password = "123456";
+ public string Password
+ {
+ get => _password;
+ set => SetProperty(ref _password, value);
+ }
+
+ public ICommand ControlCommand { get; set; }
+
+ public void UpdateMessage(string message)
+ {
+ DeviceStatus = message;
+ }
+
+ public MainViewModel()
+ {
+ ControlCommand = new AsyncRelayCommand(val =>
+ {
+ switch (val)
+ {
+ case "Lock":
+ Operation = ViewModels.OperationType.LOCK;
+ break;
+ case "Unlock":
+ Operation = ViewModels.OperationType.UNLOCK;
+ break;
+ case "SetPassword":
+ Operation = ViewModels.OperationType.SET_PASSWORD;
+ break;
+ default:
+ Operation = null;
+ break;
+ }
+
+ return Task.CompletedTask;
+ });
+ }
+}
\ No newline at end of file
diff --git a/NFCLockDemoV2/ViewModels/OperationType.cs b/NFCLockDemoV2/ViewModels/OperationType.cs
new file mode 100644
index 0000000..fc1310e
--- /dev/null
+++ b/NFCLockDemoV2/ViewModels/OperationType.cs
@@ -0,0 +1,22 @@
+namespace NFCLockDemoV2.ViewModels;
+
+///
+/// NFC 操作类型
+///
+public enum OperationType
+{
+ ///
+ /// 解锁
+ ///
+ UNLOCK,
+
+ ///
+ /// 锁定
+ ///
+ LOCK,
+
+ ///
+ /// 设置密钥
+ ///
+ SET_PASSWORD,
+}