3using Android.Content.PM;
7using AndroidX.Core.View;
8using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
16using Plugin.Firebase.CloudMessaging;
17using System.Runtime.Versioning;
19using System.Text.Json;
23 [Activity(Exported =
true, Theme =
"@style/Maui.SplashTheme", MainLauncher =
true, Name =
"com.tag.NeuroAccess.MainActivity",
24 ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density | ConfigChanges.Locale,
25 ScreenOrientation = ScreenOrientation.Portrait, LaunchMode = LaunchMode.SingleTop)]
28 NfcAdapter.ActionNdefDiscovered],
29 Categories = [Intent.CategoryDefault], DataMimeType =
"*/*")
35 Categories = [Intent.CategoryDefault, Intent.CategoryBrowsable],
36 DataSchemes = [
"iotid",
"iotdisco",
"iotsc",
"tagsign",
"obinfo",
"edaler",
"nfeat",
"xmpp",
"aes256",
"neuroaccess"])]
45 Categories = [Intent.CategoryDefault, Intent.CategoryBrowsable])]
48 private static NfcAdapter? nfcAdapter =
null;
50 private void CreateNotificationChannelsIfNeeded()
52 if (Build.VERSION.SdkInt >= BuildVersionCodes.O && OperatingSystem.IsAndroidVersionAtLeast(26))
53 this.CreateNotificationChannels();
56 [SupportedOSPlatform(
"android26.0")]
57 private void CreateNotificationChannels()
59 NotificationChannel MessagesChannel =
new(
"Messages",
"Instant Messages", NotificationImportance.High)
61 Description =
"Channel for incoming Instant Message notifications"
64 NotificationChannel PetitionsChannel =
new(
"Petitions",
"Petitions sent by other users", NotificationImportance.High)
66 Description =
"Channel for incoming Contract or Identity Peititions, such as Review or Signature Requests"
69 NotificationChannel IdentitiesChannel =
new(
"Identities",
"Identity events", NotificationImportance.High)
71 Description =
"Channel for events relating to the digital identity"
74 NotificationChannel ContractsChannel =
new(
"Contracts",
"Contract events", NotificationImportance.High)
76 Description =
"Channel for events relating to smart contracts"
79 NotificationChannel EDalerChannel =
new(
"eDaler",
"eDaler events", NotificationImportance.High)
81 Description =
"Channel for events relating to the eDaler wallet balance"
84 NotificationChannel TokensChannel =
new(
"Tokens",
"Token events", NotificationImportance.High)
86 Description =
"Channel for events relating to Neuro-Feature tokens"
89 NotificationManager? NotificationManager = this.GetSystemService(
NotificationService) as NotificationManager;
90 NotificationManager?.CreateNotificationChannels(
new List<NotificationChannel>()
92 MessagesChannel, PetitionsChannel, IdentitiesChannel, ContractsChannel, EDalerChannel, TokensChannel
94 FirebaseCloudMessagingImplementation.ChannelId =
"Messages";
98 protected override async
void OnCreate(Bundle? savedInstanceState)
102 base.OnCreate(savedInstanceState);
103 this.CreateNotificationChannelsIfNeeded();
104 nfcAdapter = NfcAdapter.GetDefaultAdapter(
this);
105 await this.HandleIntent(this.Intent);
109 StringBuilder msg =
new();
111 msg.AppendLine(
"An error occurred in the Android MainActivity.OnPostCreate method.");
112 msg.AppendLine(
"Exception message:");
113 msg.Append(ex.Message);
114 msg.AppendLine(
"\n\n");
115 msg.AppendLine(
"```");
116 msg.AppendLine(ex.StackTrace);
117 msg.AppendLine(
"```");
119 await
App.SendAlertAsync(msg.ToString(),
"text/plain");
122 App.
Current?.On<
Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
123 if (this.Window is
null)
125 WindowCompat.SetDecorFitsSystemWindows(this.Window,
false);
126 if (OperatingSystem.IsAndroidVersionAtLeast(23) && !OperatingSystem.IsAndroidVersionAtLeast(35))
129 this.Window.SetStatusBarColor(Android.Graphics.Color.Transparent);
130 this.Window.SetNavigationBarColor(Android.Graphics.Color.Transparent);
134 protected override void OnResume()
138 if (nfcAdapter is not
null)
140 Intent Intent =
new Intent(
this, this.GetType()).AddFlags(ActivityFlags.SingleTop);
142 PendingIntentFlags Flags = PendingIntentFlags.UpdateCurrent;
143 if (OperatingSystem.IsAndroidVersionAtLeast(31))
145 Flags |= PendingIntentFlags.Mutable;
148 PendingIntent? PendingIntent = Android.App.PendingIntent.GetActivity(
this, 0, Intent, Flags);
149 nfcAdapter.EnableForegroundDispatch(
this, PendingIntent,
null,
null);
152 this.RemoveAllNotifications();
155 protected override void OnPause()
158 nfcAdapter?.DisableForegroundDispatch(
this);
161 protected override async
void OnNewIntent(Intent? Intent)
163 base.OnNewIntent(Intent);
164 await this.HandleIntent(Intent,
false);
167 private async Task HandleIntent(Intent? intent,
bool Defer =
true)
181 if (intent.Extras is not
null && intent.Extras.ContainsKey(
"notificationIntent"))
183 string? payload = intent.Extras.GetString(
"notificationIntent");
184 if (!
string.IsNullOrEmpty(payload))
189 if (parsed is not
null)
191 parsed.Presentation = this.ResolvePresentation(intent.Extras, parsed.
Presentation);
205 else if (intent.Action == Intent.ActionView)
207 string? Url = intent.Data?.ToString();
208 if (!
string.IsNullOrEmpty(Url))
218 else if (intent.Extras is not
null && intent.Extras.ContainsKey(
"gcm.notification.body"))
220 string? Body = intent.Extras.GetString(
"gcm.notification.body");
221 string? Title = intent.Extras.GetString(
"gcm.notification.title");
226 Title = Title ??
string.Empty,
232 string Raw = intent.Extras.ToString() ??
string.Empty;
237 else if (intent.Action == NfcAdapter.ActionTagDiscovered ||
238 intent.Action == NfcAdapter.ActionNdefDiscovered ||
239 intent.Action == NfcAdapter.ActionTechDiscovered)
242 if (OperatingSystem.IsAndroidVersionAtLeast(33))
243 Tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag, Java.Lang.Class.FromType(typeof(Tag))) as Tag;
245 Tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
249 byte[]? Id = Tag.GetId();
253 string[]? TechList = Tag.GetTechList();
254 if (TechList is
null)
257 List<INfcInterface> Interfaces = [];
259 foreach (
string Tech
in TechList)
263 case "android.nfc.tech.IsoDep":
264 IsoDep? IsoDep = IsoDep.Get(Tag);
265 if (IsoDep is not
null)
266 Interfaces.Add(
new IsoDepInterface(Tag, IsoDep));
269 case "android.nfc.tech.MifareClassic":
270 MifareClassic? MifareClassic = MifareClassic.Get(Tag);
271 if (MifareClassic is not
null)
272 Interfaces.Add(
new MifareClassicInterface(Tag, MifareClassic));
275 case "android.nfc.tech.MifareUltralight":
276 MifareUltralight? MifareUltralight = MifareUltralight.Get(Tag);
277 if (MifareUltralight is not
null)
278 Interfaces.Add(
new MifareUltralightInterface(Tag, MifareUltralight));
281 case "android.nfc.tech.Ndef":
282 Ndef? Ndef = Ndef.Get(Tag);
283 if (Ndef is not
null)
284 Interfaces.Add(
new NdefInterface(Tag, Ndef));
287 case "android.nfc.tech.NdefFormatable":
288 NdefFormatable? NdefFormatable = NdefFormatable.Get(Tag);
289 if (NdefFormatable is not
null)
290 Interfaces.Add(
new NdefFormatableInterface(Tag, NdefFormatable));
293 case "android.nfc.tech.NfcA":
294 NfcA? NfcA = NfcA.Get(Tag);
295 if (NfcA is not
null)
296 Interfaces.Add(
new NfcAInterface(Tag, NfcA));
299 case "android.nfc.tech.NfcB":
300 NfcB? NfcB = NfcB.Get(Tag);
301 if (NfcB is not
null)
302 Interfaces.Add(
new NfcBInterface(Tag, NfcB));
305 case "android.nfc.tech.NfcBarcode":
306 NfcBarcode? NfcBarcode = NfcBarcode.Get(Tag);
307 if (NfcBarcode is not
null)
308 Interfaces.Add(
new NfcBarcodeInterface(Tag, NfcBarcode));
311 case "android.nfc.tech.NfcF":
312 NfcF? NfcF = NfcF.Get(Tag);
313 if (NfcF is not
null)
314 Interfaces.Add(
new NfcFInterface(Tag, NfcF));
317 case "android.nfc.tech.NfcV":
318 NfcV? NfcV = NfcV.Get(Tag);
319 if (NfcV is not
null)
320 Interfaces.Add(
new NfcVInterface(Tag, NfcV));
326 NfcTag NfcTag =
new(Id, [.. Interfaces]);
355 if (extras.ContainsKey(
"silent"))
357 string? value = extras.GetString(
"silent");
358 if (this.IsTrue(value))
362 if (extras.ContainsKey(
"delivery.silent"))
364 string? value = extras.GetString(
"delivery.silent");
365 if (this.IsTrue(value))
372 private bool IsTrue(
string? value)
374 if (
string.IsNullOrWhiteSpace(value))
377 return value.Equals(
"1", StringComparison.OrdinalIgnoreCase) ||
378 value.Equals(
"true", StringComparison.OrdinalIgnoreCase) ||
379 value.Equals(
"yes", StringComparison.OrdinalIgnoreCase);
383 private void RemoveAllNotifications()
385 NotificationManager? Manager = (NotificationManager?)this.GetSystemService(
NotificationService);
386 Manager?.CancelAll();
Represents an instance of the Neuro-Access app.
static new? App Current
Gets the current application instance.
Contains intent action constants used for inter-component communication within the app.
const string OpenUrl
Action used to open a URL, typically triggered by deep linking.
const string NfcTagDiscovered
Action triggered when an NFC tag is discovered.
const string Messages
Messages channel
A set of never changing property constants and helpful values.
Represents an application intent containing an action, optional data, and an optional payload.
The IntentService class is responsible for handling and processing application intents in a cross‑pla...
void QueueIntent(AppIntent intent)
Queues an intent for later processing.
async Task ProcessIntentAsync(AppIntent intent)
Processes a single intent asynchronously.
Platform-neutral intent describing how to route a notification.
NotificationPresentation Presentation
Gets or sets how the notification should be presented.
Base class that references services in the app.
static IServiceProvider Provider
The service provider for the app. This is set before the app is started, and will be used to resolve ...
static ILogService LogService
Log service.
Defines the contract for a service that handles application intents.
Interface for the redesigned notification service.
Renders local notifications on the platform.
NotificationAction
Actions that can be routed from notifications.
NotificationPresentation
Presentation preference for a notification intent.
NotificationSource
Describes the source producing a notification.