Plugin.NFC added to rpoject
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using System;
|
||||
|
||||
namespace Plugin.NFC
|
||||
{
|
||||
/// <summary>
|
||||
/// Cross NFC (Android specific)
|
||||
/// </summary>
|
||||
public static partial class CrossNFC
|
||||
{
|
||||
internal static ActivityLifecycleContextListener lifecycleListener;
|
||||
|
||||
/// <summary>
|
||||
/// Initialization
|
||||
/// </summary>
|
||||
/// <param name="application">Android <see cref="Application"/></param>
|
||||
public static void Init(Application application)
|
||||
{
|
||||
if (lifecycleListener != null) return;
|
||||
lifecycleListener = new ActivityLifecycleContextListener();
|
||||
application.RegisterActivityLifecycleCallbacks(lifecycleListener);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialization
|
||||
/// </summary>
|
||||
/// <param name="activity">Android <see cref="Activity"/></param>
|
||||
public static void Init(Activity activity)
|
||||
{
|
||||
Init(activity.Application);
|
||||
lifecycleListener.Activity = activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides Activity.OnNewIntent()
|
||||
/// </summary>
|
||||
/// <param name="intent">Android <see cref="Intent"/></param>
|
||||
public static void OnNewIntent(Intent intent) => ((NFCImplementation)Current).HandleNewIntent(intent);
|
||||
|
||||
/// <summary>
|
||||
/// Overrides Activity.OnResume()
|
||||
/// </summary>
|
||||
public static void OnResume() => ((NFCImplementation)Current).HandleOnResume();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current Android <see cref="Context"/>
|
||||
/// </summary>
|
||||
internal static Context AppContext => Application.Context;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current Android <see cref="Activity"/>
|
||||
/// </summary>
|
||||
/// <param name="throwError"></param>
|
||||
/// <returns></returns>
|
||||
internal static Activity GetCurrentActivity(bool throwError)
|
||||
{
|
||||
var activity = lifecycleListener?.Activity;
|
||||
if (throwError && activity == null)
|
||||
throw new NullReferenceException("The current Activity can not be detected. Ensure that you have called Init in your Activity or Application class.");
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// James Montemagno's ActivityLifecycleContextListener from CurrentActivityPlugin
|
||||
/// <see href="https://github.com/jamesmontemagno/CurrentActivityPlugin"/>
|
||||
/// </summary>
|
||||
class ActivityLifecycleContextListener : Java.Lang.Object, Application.IActivityLifecycleCallbacks
|
||||
{
|
||||
WeakReference<Activity> _currentActivity = new WeakReference<Activity>(null);
|
||||
|
||||
internal Context Context => Activity ?? Application.Context;
|
||||
|
||||
internal Activity Activity
|
||||
{
|
||||
get => _currentActivity.TryGetTarget(out var a) ? a : null;
|
||||
set => _currentActivity.SetTarget(value);
|
||||
}
|
||||
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityCreated(Activity activity, Bundle savedInstanceState) => Activity = activity;
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityDestroyed(Activity activity) { }
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityPaused(Activity activity) => Activity = activity;
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityResumed(Activity activity) => Activity = activity;
|
||||
void Application.IActivityLifecycleCallbacks.OnActivitySaveInstanceState(Activity activity, Bundle outState) { }
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityStarted(Activity activity) { }
|
||||
void Application.IActivityLifecycleCallbacks.OnActivityStopped(Activity activity) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
using Android;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Nfc;
|
||||
using Android.Nfc.Tech;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Plugin.NFC
|
||||
{
|
||||
/// <summary>
|
||||
/// Android implementation of <see cref="INFC"/>
|
||||
/// </summary>
|
||||
public class NFCImplementation : INFC
|
||||
{
|
||||
public event EventHandler OnTagConnected;
|
||||
public event EventHandler OnTagDisconnected;
|
||||
public event NdefMessageReceivedEventHandler OnMessageReceived;
|
||||
public event NdefMessagePublishedEventHandler OnMessagePublished;
|
||||
public event TagDiscoveredEventHandler OnTagDiscovered;
|
||||
public event EventHandler OniOSReadingSessionCancelled;
|
||||
public event TagListeningStatusChangedEventHandler OnTagListeningStatusChanged;
|
||||
|
||||
readonly NfcAdapter _nfcAdapter;
|
||||
|
||||
bool _isListening;
|
||||
bool _isWriting;
|
||||
bool _isFormatting;
|
||||
Tag _currentTag;
|
||||
|
||||
/// <summary>
|
||||
/// Current Android <see cref="Context"/>
|
||||
/// </summary>
|
||||
Context CurrentContext => CrossNFC.AppContext;
|
||||
|
||||
/// <summary>
|
||||
/// Current Android <see cref="Activity"/>
|
||||
/// </summary>
|
||||
Activity CurrentActivity => CrossNFC.GetCurrentActivity(true);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if NFC Feature is available
|
||||
/// </summary>
|
||||
public bool IsAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CurrentContext.CheckCallingOrSelfPermission(Manifest.Permission.Nfc) != Android.Content.PM.Permission.Granted)
|
||||
return false;
|
||||
return _nfcAdapter != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if NFC Feature is enabled
|
||||
/// </summary>
|
||||
public bool IsEnabled => IsAvailable && _nfcAdapter.IsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if writing mode is supported
|
||||
/// </summary>
|
||||
public bool IsWritingTagSupported => NFCUtils.IsWritingSupported();
|
||||
|
||||
/// <summary>
|
||||
/// NFC configuration
|
||||
/// </summary>
|
||||
public NfcConfiguration Configuration { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public NFCImplementation()
|
||||
{
|
||||
_nfcAdapter = NfcAdapter.GetDefaultAdapter(CurrentContext);
|
||||
Configuration = NfcConfiguration.GetDefaultConfiguration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update NFC configuration
|
||||
/// </summary>
|
||||
/// <param name="configuration"><see cref="NfcConfiguration"/></param>
|
||||
public void SetConfiguration(NfcConfiguration configuration) => Configuration.Update(configuration);
|
||||
|
||||
/// <summary>
|
||||
/// Starts tags detection
|
||||
/// </summary>
|
||||
public void StartListening()
|
||||
{
|
||||
if (_nfcAdapter == null)
|
||||
return;
|
||||
|
||||
var intent = new Intent(CurrentActivity, CurrentActivity.GetType()).AddFlags(ActivityFlags.SingleTop);
|
||||
|
||||
// We don't use MonoAndroid12.0 as targetframework for easier backward compatibility:
|
||||
// MonoAndroid12.0 needs JDK 11.
|
||||
PendingIntentFlags pendingIntentFlags = 0;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.S)
|
||||
pendingIntentFlags = PendingIntentFlags.Mutable;
|
||||
#else
|
||||
if ((int)Android.OS.Build.VERSION.SdkInt >= 31) //Android.OS.BuildVersionCodes.S
|
||||
pendingIntentFlags = (PendingIntentFlags)33554432; //PendingIntentFlags.Mutable
|
||||
#endif
|
||||
|
||||
var pendingIntent = PendingIntent.GetActivity(CurrentActivity, 0, intent, pendingIntentFlags);
|
||||
|
||||
var ndefFilter = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
|
||||
ndefFilter.AddDataType("*/*");
|
||||
|
||||
var tagFilter = new IntentFilter(NfcAdapter.ActionTagDiscovered);
|
||||
tagFilter.AddCategory(Intent.CategoryDefault);
|
||||
|
||||
var filters = new IntentFilter[] { ndefFilter, tagFilter };
|
||||
|
||||
_nfcAdapter.EnableForegroundDispatch(CurrentActivity, pendingIntent, filters, null);
|
||||
|
||||
_isListening = true;
|
||||
OnTagListeningStatusChanged?.Invoke(_isListening);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops tags detection
|
||||
/// </summary>
|
||||
public void StopListening()
|
||||
{
|
||||
DisablePublishing();
|
||||
if (_nfcAdapter != null)
|
||||
_nfcAdapter.DisableForegroundDispatch(CurrentActivity);
|
||||
|
||||
_isListening = false;
|
||||
OnTagListeningStatusChanged?.Invoke(_isListening);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts tag publishing (writing or formatting)
|
||||
/// </summary>
|
||||
/// <param name="clearMessage">Format tag</param>
|
||||
public void StartPublishing(bool clearMessage = false)
|
||||
{
|
||||
if (!IsWritingTagSupported)
|
||||
return;
|
||||
|
||||
_isWriting = true;
|
||||
_isFormatting = clearMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops tag publishing
|
||||
/// </summary>
|
||||
public void StopPublishing() => DisablePublishing();
|
||||
|
||||
/// <summary>
|
||||
/// Publish or write a message on a tag
|
||||
/// </summary>
|
||||
/// <param name="tagInfo">see <see cref="ITagInfo"/></param>
|
||||
/// <param name="makeReadOnly">make tag read-only</param>
|
||||
public void PublishMessage(ITagInfo tagInfo, bool makeReadOnly = false) => WriteOrClearMessage(tagInfo, false, makeReadOnly);
|
||||
|
||||
/// <summary>
|
||||
/// Format tag
|
||||
/// </summary>
|
||||
/// <param name="tagInfo">see <see cref="ITagInfo"/></param>
|
||||
public void ClearMessage(ITagInfo tagInfo) => WriteOrClearMessage(tagInfo, true);
|
||||
|
||||
/// <summary>
|
||||
/// Write or Clear a NDEF message
|
||||
/// </summary>
|
||||
/// <param name="tagInfo"><see cref="ITagInfo"/></param>
|
||||
/// <param name="clearMessage">Clear Message</param>
|
||||
/// <param name="makeReadOnly">Make tag read-only</param>
|
||||
internal void WriteOrClearMessage(ITagInfo tagInfo, bool clearMessage = false, bool makeReadOnly = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentTag == null)
|
||||
throw new Exception(Configuration.Messages.NFCErrorMissingTag);
|
||||
|
||||
if (tagInfo == null)
|
||||
throw new Exception(Configuration.Messages.NFCErrorMissingTagInfo);
|
||||
|
||||
var ndef = Ndef.Get(_currentTag);
|
||||
if (ndef != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ndef.IsWritable)
|
||||
throw new Exception(Configuration.Messages.NFCErrorReadOnlyTag);
|
||||
|
||||
if (ndef.MaxSize < NFCUtils.GetSize(tagInfo.Records))
|
||||
throw new Exception(Configuration.Messages.NFCErrorCapacityTag);
|
||||
|
||||
ndef.Connect();
|
||||
OnTagConnected?.Invoke(null, EventArgs.Empty);
|
||||
|
||||
NdefMessage message = null;
|
||||
if (clearMessage)
|
||||
{
|
||||
message = GetEmptyNdefMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
var records = new List<NdefRecord>();
|
||||
for (var i = 0; i < tagInfo.Records.Length; i++)
|
||||
{
|
||||
var record = tagInfo.Records[i];
|
||||
if (GetAndroidNdefRecord(record) is NdefRecord ndefRecord)
|
||||
records.Add(ndefRecord);
|
||||
}
|
||||
|
||||
if (records.Any())
|
||||
message = new NdefMessage(records.ToArray());
|
||||
}
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
ndef.WriteNdefMessage(message);
|
||||
|
||||
if (!clearMessage && makeReadOnly)
|
||||
{
|
||||
if (!MakeReadOnly(ndef))
|
||||
Console.WriteLine("Cannot lock tag");
|
||||
}
|
||||
|
||||
var nTag = GetTagInfo(_currentTag, ndef.NdefMessage);
|
||||
OnMessagePublished?.Invoke(nTag);
|
||||
}
|
||||
else
|
||||
throw new Exception(Configuration.Messages.NFCErrorWrite);
|
||||
}
|
||||
catch (Android.Nfc.TagLostException tlex)
|
||||
{
|
||||
throw new Exception("Tag Lost Error: " + tlex.Message);
|
||||
}
|
||||
catch (Java.IO.IOException ioex)
|
||||
{
|
||||
throw new Exception("Tag IO Error: " + ioex.Message);
|
||||
}
|
||||
catch (Android.Nfc.FormatException fe)
|
||||
{
|
||||
throw new Exception("Tag Format Error: " + fe.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Tag Error:" + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ndef.IsConnected)
|
||||
ndef.Close();
|
||||
|
||||
_currentTag = null;
|
||||
OnTagDisconnected?.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new Exception(Configuration.Messages.NFCErrorNotCompliantTag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StopPublishingAndThrowError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Android OnNewIntent
|
||||
/// </summary>
|
||||
/// <param name="intent">Android <see cref="Intent"/></param>
|
||||
internal void HandleNewIntent(Intent intent)
|
||||
{
|
||||
if (intent == null)
|
||||
return;
|
||||
|
||||
if (intent.Action == NfcAdapter.ActionTagDiscovered || intent.Action == NfcAdapter.ActionNdefDiscovered)
|
||||
{
|
||||
_currentTag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
|
||||
if (_currentTag != null)
|
||||
{
|
||||
var nTag = GetTagInfo(_currentTag);
|
||||
if (_isWriting)
|
||||
{
|
||||
// Write mode
|
||||
OnTagDiscovered?.Invoke(nTag, _isFormatting);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read mode
|
||||
OnMessageReceived?.Invoke(nTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Android OnResume
|
||||
/// </summary>
|
||||
internal void HandleOnResume()
|
||||
{
|
||||
// Android 10 fix:
|
||||
// If listening mode is already enable, we restart listening when activity is resumed
|
||||
if (_isListening)
|
||||
StartListening();
|
||||
}
|
||||
|
||||
#region Private
|
||||
|
||||
/// <summary>
|
||||
/// Stops publishing and throws error
|
||||
/// </summary>
|
||||
/// <param name="message">message</param>
|
||||
void StopPublishingAndThrowError(string message)
|
||||
{
|
||||
StopPublishing();
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate publishing
|
||||
/// </summary>
|
||||
void DisablePublishing()
|
||||
{
|
||||
_isWriting = false;
|
||||
_isFormatting = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an array of <see cref="NdefRecord"/> into an array of <see cref="NFCNdefRecord"/>
|
||||
/// </summary>
|
||||
/// <param name="records">Array of <see cref="NdefRecord"/></param>
|
||||
/// <returns>Array of <see cref="NFCNdefRecord"/></returns>
|
||||
NFCNdefRecord[] GetRecords(NdefRecord[] records)
|
||||
{
|
||||
var results = new NFCNdefRecord[records.Length];
|
||||
for (var i = 0; i < records.Length; i++)
|
||||
{
|
||||
var ndefRecord = new NFCNdefRecord
|
||||
{
|
||||
TypeFormat = (NFCNdefTypeFormat)records[i].Tnf,
|
||||
Uri = records[i].ToUri()?.ToString(),
|
||||
MimeType = records[i].ToMimeType(),
|
||||
Payload = records[i].GetPayload()
|
||||
};
|
||||
results.SetValue(ndefRecord, i);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns informations contains in NFC Tag
|
||||
/// </summary>
|
||||
/// <param name="tag">Android <see cref="Tag"/></param>
|
||||
/// <param name="ndefMessage">Android <see cref="NdefMessage"/></param>
|
||||
/// <returns><see cref="ITagInfo"/></returns>
|
||||
ITagInfo GetTagInfo(Tag tag, NdefMessage ndefMessage = null)
|
||||
{
|
||||
if (tag == null)
|
||||
return null;
|
||||
|
||||
var ndef = Ndef.Get(tag);
|
||||
var nTag = new TagInfo(tag.GetId(), ndef != null);
|
||||
|
||||
if (ndef != null)
|
||||
{
|
||||
nTag.Capacity = ndef.MaxSize;
|
||||
nTag.IsWritable = ndef.IsWritable;
|
||||
|
||||
if (ndefMessage == null)
|
||||
ndefMessage = ndef.CachedNdefMessage;
|
||||
|
||||
if (ndefMessage != null)
|
||||
{
|
||||
var records = ndefMessage.GetRecords();
|
||||
nTag.Records = GetRecords(records);
|
||||
}
|
||||
}
|
||||
|
||||
return nTag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a <see cref="NFCNdefRecord"/> into an Android <see cref="NdefRecord"/>
|
||||
/// </summary>
|
||||
/// <param name="record">Object <see cref="NFCNdefRecord"/></param>
|
||||
/// <returns>Android <see cref="NdefRecord"/></returns>
|
||||
NdefRecord GetAndroidNdefRecord(NFCNdefRecord record)
|
||||
{
|
||||
if (record == null)
|
||||
return null;
|
||||
|
||||
NdefRecord ndefRecord = null;
|
||||
switch (record.TypeFormat)
|
||||
{
|
||||
case NFCNdefTypeFormat.WellKnown:
|
||||
var languageCode = record.LanguageCode;
|
||||
if (string.IsNullOrWhiteSpace(languageCode)) languageCode = Configuration.DefaultLanguageCode;
|
||||
ndefRecord = NdefRecord.CreateTextRecord(languageCode.Substring(0, 2), Encoding.UTF8.GetString(record.Payload));
|
||||
break;
|
||||
case NFCNdefTypeFormat.Mime:
|
||||
ndefRecord = NdefRecord.CreateMime(record.MimeType, record.Payload);
|
||||
break;
|
||||
case NFCNdefTypeFormat.Uri:
|
||||
ndefRecord = NdefRecord.CreateUri(Encoding.UTF8.GetString(record.Payload));
|
||||
break;
|
||||
case NFCNdefTypeFormat.External:
|
||||
ndefRecord = NdefRecord.CreateExternal(record.ExternalDomain, record.ExternalType, record.Payload);
|
||||
break;
|
||||
case NFCNdefTypeFormat.Empty:
|
||||
ndefRecord = GetEmptyNdefRecord();
|
||||
break;
|
||||
case NFCNdefTypeFormat.Unknown:
|
||||
case NFCNdefTypeFormat.Unchanged:
|
||||
case NFCNdefTypeFormat.Reserved:
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return ndefRecord;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty Android <see cref="NdefRecord"/>
|
||||
/// </summary>
|
||||
/// <returns>Android <see cref="NdefRecord"/></returns>
|
||||
NdefRecord GetEmptyNdefRecord()
|
||||
{
|
||||
var empty = Array.Empty<byte>();
|
||||
return new NdefRecord(NdefRecord.TnfEmpty, empty, empty, empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty Android <see cref="NdefMessage"/>
|
||||
/// </summary>
|
||||
/// <returns>Android <see cref="NdefMessage"/></returns>
|
||||
NdefMessage GetEmptyNdefMessage()
|
||||
{
|
||||
var records = new NdefRecord[1];
|
||||
records[0] = GetEmptyNdefRecord();
|
||||
return new NdefMessage(records);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a tag read-only
|
||||
/// WARNING: This operation is permanent
|
||||
/// </summary>
|
||||
/// <param name="ndef"><see cref="Ndef"/></param>
|
||||
/// <returns>boolean</returns>
|
||||
bool MakeReadOnly(Ndef ndef)
|
||||
{
|
||||
if (ndef == null)
|
||||
return false;
|
||||
|
||||
var result = false;
|
||||
var newConnection = false;
|
||||
|
||||
if (!ndef.IsConnected)
|
||||
{
|
||||
newConnection = true;
|
||||
ndef.Connect();
|
||||
}
|
||||
|
||||
if (ndef.CanMakeReadOnly())
|
||||
result = ndef.MakeReadOnly();
|
||||
|
||||
if (newConnection && ndef.IsConnected)
|
||||
ndef.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NFC Status Event Listener
|
||||
|
||||
NfcBroadcastReceiver _nfcBroadcastReceiver;
|
||||
|
||||
event OnNfcStatusChangedEventHandler _onNfcStatusChangedInternal;
|
||||
|
||||
public event OnNfcStatusChangedEventHandler OnNfcStatusChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
var wasRunning = _onNfcStatusChangedInternal != null;
|
||||
_onNfcStatusChangedInternal += value;
|
||||
if (!wasRunning && _onNfcStatusChangedInternal != null)
|
||||
{
|
||||
RegisterListener();
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
var wasRunning = _onNfcStatusChangedInternal != null;
|
||||
_onNfcStatusChangedInternal -= value;
|
||||
if (wasRunning && _onNfcStatusChangedInternal == null)
|
||||
{
|
||||
UnRegisterListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register NFC Broadcast Receiver
|
||||
/// </summary>
|
||||
void RegisterListener()
|
||||
{
|
||||
_nfcBroadcastReceiver = new NfcBroadcastReceiver(OnNfcStatusChange);
|
||||
CurrentContext?.RegisterReceiver(_nfcBroadcastReceiver, new IntentFilter(NfcAdapter.ActionAdapterStateChanged));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister NFC Broadcast Receiver
|
||||
/// </summary>
|
||||
void UnRegisterListener()
|
||||
{
|
||||
if (_nfcBroadcastReceiver == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
CurrentContext?.UnregisterReceiver(_nfcBroadcastReceiver);
|
||||
}
|
||||
catch (Java.Lang.IllegalArgumentException ex)
|
||||
{
|
||||
throw new Exception("NFC Broadcast Receiver Error: " + ex.Message);
|
||||
}
|
||||
|
||||
_nfcBroadcastReceiver.Dispose();
|
||||
_nfcBroadcastReceiver = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when NFC status has changed
|
||||
/// </summary>
|
||||
void OnNfcStatusChange() => _onNfcStatusChangedInternal?.Invoke(IsEnabled);
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast Receiver to check NFC feature availability
|
||||
/// </summary>
|
||||
[BroadcastReceiver(Enabled = true, Exported = false, Label = "NFC Status Broadcast Receiver")]
|
||||
class NfcBroadcastReceiver : BroadcastReceiver
|
||||
{
|
||||
Action _onChanged;
|
||||
|
||||
public NfcBroadcastReceiver() { }
|
||||
public NfcBroadcastReceiver(Action onChanged)
|
||||
{
|
||||
_onChanged = onChanged;
|
||||
}
|
||||
|
||||
public override async void OnReceive(Context context, Intent intent)
|
||||
{
|
||||
if (intent.Action == NfcAdapter.ActionAdapterStateChanged)
|
||||
{
|
||||
var state = intent.GetIntExtra(NfcAdapter.ExtraAdapterState, default);
|
||||
if (state == NfcAdapter.StateOff || state == NfcAdapter.StateOn)
|
||||
{
|
||||
// await 1500ms to ensure that the status updates
|
||||
await Task.Delay(1500);
|
||||
_onChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user