Najoom 1.0.1
dotnet add package Najoom --version 1.0.1
NuGet\Install-Package Najoom -Version 1.0.1
<PackageReference Include="Najoom" Version="1.0.1" />
<PackageVersion Include="Najoom" Version="1.0.1" />
<PackageReference Include="Najoom" />
paket add Najoom --version 1.0.1
#r "nuget: Najoom, 1.0.1"
#:package Najoom@1.0.1
#addin nuget:?package=Najoom&version=1.0.1
#tool nuget:?package=Najoom&version=1.0.1
Najoom Lifestyle SDK for .NET MAUI
Official .NET MAUI bindings for the Najoom Lifestyle SDK. A single package embeds the Najoom offers / coupons experience into a MAUI app on both Android and iOS.
You give the SDK a session token; it renders its entire UI itself — home, offer categories, merchant listings, offer details with maps, coupons, favourites, redemption (QR / code), and contacts. Your app builds none of those screens.
| Target | Included |
|---|---|
net9.0-android |
Managed binding + all runtime AARs (Jetpack Compose, Coil, Google Maps, Huawei Map Kit, Retrofit/OkHttp, Nimbus JWT) |
net9.0-ios |
Managed binding + native NajoomLifestyles.xcframework (device + simulator slices) |
One PackageReference covers both platforms.
Install
dotnet add package Najoom --version 1.0.1
<PackageReference Include="Najoom" Version="1.0.1" />
Requirements
- .NET 9 with the MAUI /
androidandiosworkloads. - Android minimum API level 24; iOS minimum 13.0.
Host-app configuration
These cannot be carried by the package and must be supplied by the consuming app.
Android — required NuGet pins (build/runtime conflict fix)
com.google.gson and a few AndroidX versions conflict with what Microsoft.Maui.Core pins. Add
these to your app project or you'll hit NU1107 at build or a crash at runtime:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.10.0.2" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core" Version="2.10.0.2" />
<PackageReference Include="Xamarin.AndroidX.SavedState.SavedState.Ktx" Version="1.4.0.2" />
</ItemGroup>
The NU1608 "version outside constraint" warnings these produce are expected and benign.
(Non-MAUI Xamarin.Android hosts must also add the GoogleGson NuGet ≥ 2.10.1 — a MAUI app
already provides it transitively.)
Android — Google Maps API key (required)
The SDK shows a Google Map on offer-detail screens. Add your key to the host
AndroidManifest.xml (play-services-maps reads it from the host, never the SDK). Without it the
app hard-crashes with IllegalStateException: API key not found when a map opens.
<application ...>
<meta-data android:name="com.google.android.geo.API_KEY" android:value="YOUR_MAPS_KEY" />
</application>
Huawei devices additionally need an AppGallery Connect project (agconnect-services.json + Map
Kit key) in the host app.
iOS
No extra references or pins — the native NajoomLifestyles.xcframework ships inside the package
and links automatically.
Initialize & launch
The one runtime input is a session token from your own login flow. No API key or encryption
keys are needed — those are embedded in the SDK. Initialization is async — only show the SDK UI
after onSuccess.
Android — launch NajoomActivity
using Com.Najoom.Lifestyles.Public;
using Microsoft.Maui.ApplicationModel;
var activity = Platform.CurrentActivity;
var intent = NajoomActivity.CreateIntent(activity, token);
activity.StartActivity(intent); // NajoomActivity self-initializes and renders its own UI
iOS — initialize, present on success
using NajoomLifestyles;
using Microsoft.Maui.ApplicationModel;
using UIKit;
NajoomSDK.Initialize(
token,
onSuccess: () => MainThread.BeginInvokeOnMainThread(() =>
{
// Grab the app's top-most view controller to present from.
var root = UIApplication.SharedApplication.KeyWindow?.RootViewController;
while (root?.PresentedViewController is not null)
root = root.PresentedViewController;
var vc = NajoomSDK.MakeContentViewController();
vc.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
root?.PresentViewController(vc, animated: true, completionHandler: null);
}),
onError: message => { /* show error, prompt re-login */ });
Session callbacks (optional, both platforms)
Three optional callbacks: session-expired, token-refresh, offer-redeemed.
Register them before launching NajoomActivity:
NajoomActivity.SetOnOfferRedeemed(new RedeemListener(token => { /* forward token to backend */ }));
NajoomActivity.SetOnRefreshToken(new RefreshTokenListener(async () => await GetFreshTokenAsync()));
RedeemListener and RefreshTokenListener are small adapter classes you add to your app —
each wraps a C# delegate in the SDK's Java interface and must extend Java.Lang.Object to cross
the JNI boundary. Paste these two classes as-is:
using Com.Najoom.Lifestyles.Public;
// Adapts an Action<string> to INajoomRedeemListener.
sealed class RedeemListener : Java.Lang.Object, INajoomRedeemListener
{
readonly Action<string> _onOfferRedeemed;
public RedeemListener(Action<string> onOfferRedeemed) => _onOfferRedeemed = onOfferRedeemed;
public void OnOfferRedeemed(string token) => _onOfferRedeemed(token);
}
// Adapts an async Func<Task<string?>> to INajoomRefreshTokenListener.
// The SDK calls OnRefreshToken on the main thread and blocks a background thread (up to 30s)
// waiting for the reply, so run the refresh OFF the main thread and deliver via
// result.OnToken(...) from whatever thread it finishes on (pass null if the refresh failed).
sealed class RefreshTokenListener : Java.Lang.Object, INajoomRefreshTokenListener
{
readonly Func<Task<string?>> _onRefreshToken;
public RefreshTokenListener(Func<Task<string?>> onRefreshToken) => _onRefreshToken = onRefreshToken;
public void OnRefreshToken(INajoomTokenCallback result) => _ = Task.Run(async () =>
{
string? newToken;
try { newToken = await _onRefreshToken(); } catch { newToken = null; }
result.OnToken(newToken);
});
}
iOS — full Initialize overload
NajoomSDK.Initialize(
token,
onSuccess: () => { /* present MakeContentViewController() */ },
onError: message => { /* show error */ },
onSessionExpired: () => { /* prompt re-login */ },
onRefreshToken: completion => Task.Run(async () =>
{
string? fresh;
try { fresh = await GetFreshTokenAsync(); } catch { fresh = null; }
completion.Provide(fresh); // any thread; null = refresh failed
}),
onOfferRedeemed: redeemToken => { /* forward opaque token to your backend */ });
Pass null for any callback you don't need.
Behaviour notes
- The SDK owns the whole screen; your app gets no navigation callbacks until the user backs out.
- Security is on by default: screenshots/recording of SDK screens are blocked, plus device integrity checks. Relaxed automatically on debug builds so emulator/QA is unaffected.
- Token carries a ~1-hour backend expiry + configurable idle timeout (default 30 min).
API surface
Android (Com.Najoom.Lifestyles.Public) — NajoomActivity.CreateIntent(context, token),
SetOnOfferRedeemed, SetOnRefreshToken; NajoomSDK.Initialize/IsInitialized/Reset;
INajoomRedeemListener, INajoomRefreshTokenListener, INajoomTokenCallback. (NajoomSDKView
is intentionally not bound — use NajoomActivity.)
iOS (NajoomLifestyles) — NajoomSDK.Initialize(token, onSuccess, onError[, onSessionExpired, onRefreshToken, onOfferRedeemed]), MakeContentViewController(), IsInitialized, Reset(),
NajoomTokenCompletion.Provide(token).
License
Proprietary. All rights reserved. See LICENSE.txt.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0-android35.0 is compatible. net9.0-ios18.0 is compatible. net10.0-android was computed. net10.0-ios was computed. |
-
net9.0-android35.0
- Xamarin.AndroidX.Activity (>= 1.12.4.1)
- Xamarin.Kotlin.StdLib (>= 2.3.10.1)
- Xamarin.KotlinX.Coroutines.Android (>= 1.10.2.3)
-
net9.0-ios18.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.1 | 130 | 7/27/2026 |