.NET MAUI SDK
Pushizo.Maui — Android ve iOS yerel SDK'larını JSON köprüsüyle saran .NET MAUI paketi (net8.0/net9.0); push, in-app, bildirim kutusu, tercihler.
Pushizo.Maui, yerel Pushizo Android (com.pushizo:pushizo-android) ve iOS (Pushizo Swift) SDK'larını sarar; tetik değerlendirme, çevrimdışı kuyruk, teslimat geri bildirimi ve in-app çizimi yerel SDK'dadır. Yüzey OneSignal v5 ile ve Flutter eklentisi ile aynıdır (C# adlandırmasıyla). Ad alanı PushizoSdk.Maui. Örnek: examples/maui-app.
| Hedef | Davranış |
|---|---|
net8.0-android, net9.0-android | Yerel Android SDK'sı (minSdk 23) |
net8.0-ios, net9.0-ios | Yerel iOS SDK'sı (iOS 15+) |
| Diğerleri (Windows, MacCatalyst) | Çağrılar etkisizdir, bir kez uyarı yazılır; bildirim kutusu ve tercihler PLATFORM_NOT_SUPPORTED döndürür (Pushizo.IsSupported) |
Kurulum
dotnet add package Pushizo.Maui// MauiProgram.cs
using PushizoSdk.Maui;
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>()
.UsePushizo("app_…", o =>
{
o.ApiUrl = "https://api.example.com";
o.RequiresPrivacyConsent = false; // true ise SetConsentGiven(true) gelene kadar ağ çağrısı yok
o.LogLevel = LogLevel.Warn;
// Android: AndroidDefaultChannelId, AndroidDefaultChannelName · iOS: IosAppGroup, IosApnsEnvironment, IosProvisionalAuthorization
});UsePushizo yerine doğrudan Pushizo.Initialize("app_…", new PushizoOptions { … }) da çağrılabilir. Aynı App ID ile tekrar çağrı etkisizdir; farklı App ID InvalidOperationException üretir. Initialize'dan önce yapılan çağrılar InvalidOperationException fırlatır.
Android
- Firebase konsolundan
google-services.jsonindirip projeye ekleyin:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<GoogleServicesJson Include="Platforms/Android/google-services.json" />
</ItemGroup>- Dashboard → Kanallar → Android Push → Firebase servis hesabı JSON'u.
POST_NOTIFICATIONS, FCM servisi ve bildirim Activity'si yerel SDK manifestinden birleşir.UsePushizoizin sonucunu yaşam döngüsü olayından otomatik alır. YalnızcaPushizo.InitializekullanıyorsanızMainActivityiçinde:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
PushizoAndroid.OnRequestPermissionsResult(requestCode);
}iOS
Platforms/iOS/Entitlements.plistiçindeaps-environment,Info.plistiçindeUIBackgroundModes→remote-notification.- Dashboard → Kanallar → iOS Push →
.p8anahtarı. - Yerel SDK swizzling kullanmaz; APNs token'ını
AppDelegate'ten iletin:
[Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) =>
PushizoIos.RegisteredForRemoteNotifications(deviceToken);
[Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) =>
PushizoIos.FailedToRegisterForRemoteNotifications(error);- Zengin medya, rozet ve teslimat onayı için Xcode'da Notification Service Extension hedefi ekleyip yerel
PushizoExtension(SPM) ya daPushizo/Extension(CocoaPods) ilePushizoNotificationServiceExtensionsınıfını kullanın; rozet paylaşımı içinIosAppGroup. Ayrıntı: iOS SDK.
İzin
bool granted = await Pushizo.Notifications.RequestPermissionAsync(fallbackToSettings: true); // reddedildiyse ayarları açar
bool current = Pushizo.Notifications.Permission;
Pushizo.Notifications.PermissionChanged += (_, e) => Console.WriteLine(e.Permission);PermissionChanged yerel SDK izin gözlemcisinden gelir ve yalnızca gerçek değişiklikte tetiklenir. İzin yoksa abonelik pending kalır; izin verilince otomatik kaydedilir.
Kullanıcı, abonelik, tag ve alias
Pushizo.SetConsentGiven(true); // false: kuyruk ve yerel kimlik temizlenir
Pushizo.Login("user_42", identityHash: hashFromYourServer); // identity verification açıksa hash zorunlu
Pushizo.Logout();
Pushizo.User.AddTag("plan", "pro");
Pushizo.User.AddTags(new Dictionary<string, string> { ["plan"] = "pro", ["city"] = "istanbul" });
Pushizo.User.RemoveTag("plan"); // RemoveTags(new[] { "plan", "city" })
IReadOnlyDictionary<string, string> tags = Pushizo.User.GetTags();
Pushizo.User.SetLanguage("tr");
Pushizo.User.AddAlias("crm_id", "42"); // AddAliases(dict), RemoveAlias("crm_id")
string? externalId = Pushizo.User.ExternalId; string? hsId = Pushizo.User.Id;
var sub = Pushizo.User.PushSubscription; // Id, Token, OptedIn, Current (PushSubscriptionState)
sub.OptIn(); sub.OptOut();
sub.Changed += (_, e) => Console.WriteLine($"{e.Previous.Id} → {e.Current.Id}");E-posta ve SMS
Pushizo.User.AddEmail("Ali@Example.com"); // → ali@example.com; geçersizse ArgumentException
Pushizo.User.RemoveEmail("ali@example.com");
Pushizo.User.AddSms("+905321234567"); // E.164 bekler; geçersizse ArgumentException
Pushizo.User.RemoveSms("+905321234567");
IReadOnlyList<string> emails = Pushizo.User.Emails; // SmsNumbers: bu cihazda kayıtlı adreslerKullanıcı tercihleri
UserPreferences prefs = await Pushizo.User.GetPreferencesAsync(); // prefs.Preferences, prefs.Categories
foreach (var category in prefs.Categories)
Console.WriteLine($"{category.Key}: {category.LocalizedName("tr")} (varsayılan {category.DefaultOptedIn})");
UserPreferences updated = await Pushizo.User.SetPreferencesAsync(new[]
{
new PreferenceInput("promo", OptedIn: false), // Channel null = tüm kanallar
new PreferenceInput("news", OptedIn: true, Channel: "email"), // ios_push | android_push | web_push | email | sms
});SetPreferencesAsync girdiyi köprüden önce doğrular (1-100 kayıt, kategori 1-64 karakter, bilinen kanal ya da null); geçersizse ArgumentException. Abonelik henüz yoksa PushizoException (NOT_READY). UserPreference: Category, Channel, OptedIn, Explicit, Source, UpdatedAt (DateTimeOffset?). Kategori modeli: Tercihler.
Bildirim olayları
Pushizo.Notifications.Clicked += (_, e) => Navigate(e.Url); // e.Notification, e.ActionId, e.Url
Pushizo.Notifications.ForegroundWillDisplay += (_, e) =>
{
if (IsChatOpen) e.PreventDefault(); // işleyici içinde eşzamanlı; gerekirse sonra e.Display()
};Uygulama bildirimle açıldığında henüz Clicked abonesi yoksa son tıklama saklanır ve ilk aboneye iletilir. PushizoNotification: Title, Body, ImageUrl, Url, DeliveryId, MessageId, Actions, Data. Olaylar yerel SDK'nın iş parçacığında tetiklenir; arayüz güncellemesi için MainThread.BeginInvokeOnMainThread kullanın.
In-app mesajlar
Pushizo.InAppMessages.AddTrigger("level", "gold"); // AddTriggers(dict), RemoveTrigger(s), ClearTriggers(), GetTriggers()
Pushizo.InAppMessages.SetScreen("cart"); // sayfanın OnAppearing'inde; ayrılırken SetScreen(null)
Pushizo.Session.SendEvent("cart_viewed");
Pushizo.InAppMessages.Paused = true;
Pushizo.InAppMessages.Clicked += (_, e) => Console.WriteLine($"{e.MessageId} {e.ActionId} {e.Url}");
Pushizo.InAppMessages.DidDisplay += (_, e) => Console.WriteLine(e.Message.Id); // WillDisplay, WillDismiss, DidDismissMesajlar yerel arayüzle çizilir (Android Dialog, iOS UIWindow). Tetik anahtarı 1-64, değer en fazla 200 karakter.
Bildirim kutusu
InboxPage page = await Pushizo.Inbox.ListAsync(limit: 20, cursor: null); // Items, UnreadCount, NextCursor, HasMore
InboxItem item = await Pushizo.Inbox.MarkReadAsync(page.Items[0].Id);
int remaining = await Pushizo.Inbox.MarkAllReadAsync();
await Pushizo.Inbox.ArchiveAsync(item.Id);
int unread = await Pushizo.Inbox.UnreadCountAsync();limit 1-200 (aralık dışıysa ArgumentOutOfRangeException). Zamanlar DateTimeOffset?.
Olaylar (outcome) ve diğerleri
Pushizo.Session.SendEvent("purchase", new Dictionary<string, object?> { ["sku"] = "A1" }, value: 129.9);
Pushizo.Notifications.ClearAll(); // bu uygulamanın bildirimleri (iOS'ta rozet de sıfırlanır)
Pushizo.Notifications.RemoveGroupedNotifications("orders"); // Android android_group / iOS thread-id
Pushizo.Notifications.RemoveNotification(n.AndroidNotificationId!.Value); // Android tepsi kimliği (iOS'ta null)
Pushizo.Notifications.RemoveNotification("istek-kimligi"); // iOS: UNNotificationRequest.identifier
Pushizo.Debug.SetLogLevel(LogLevel.Debug); // None | Error | Warn | Info | DebugHata kodları
Bildirim kutusu ve tercih hataları PushizoException.Code ile gelir:
| Kod | Anlam |
|---|---|
NOT_READY | Abonelik/kullanıcı kaydı henüz tamamlanmadı. |
INVALID_ARGUMENT | Yerel SDK girdiyi reddetti. |
PLATFORM_NOT_SUPPORTED | Android/iOS dışı hedef (Windows, MacCatalyst). |
INVALID_RESPONSE | Köprü yanıtı ayrıştırılamadı. |
HS_… | Sunucu hata kodu; katalog: Hatalar. |
C# tarafındaki doğrulama hataları (ArgumentException, ArgumentOutOfRangeException) köprüye gitmeden fırlatılır.
Test
# Paylaşılan katman + birim testleri (iş yükü gerekmez)
dotnet test sdk/maui/tests/Pushizo.Maui.Tests -p:PushizoIncludeAndroid=false
# Android (maui-android iş yükü, JDK 17, ANDROID_HOME, PATH'te gradle 8.x)
dotnet build sdk/maui/src/Pushizo.Maui -f net9.0-android
# iOS (macOS + Xcode 15+ + maui-ios iş yükü)
dotnet build sdk/maui/src/Pushizo.Maui -f net9.0-iosSorun giderme
| Belirti | Neden / çözüm |
|---|---|
InvalidOperationException: Önce Pushizo.Initialize çağrılmalı | UsePushizo/Initialize çağrılmadan SDK kullanıldı. |
| Android'de izin sonucu gelmiyor | UsePushizo yerine Initialize kullanılıyor ve PushizoAndroid.OnRequestPermissionsResult iletilmiyor. |
| iOS'ta abonelik oluşmuyor | AppDelegate'te PushizoIos.RegisteredForRemoteNotifications çağrılmıyor ya da aps-environment eksik. |
| Olay işleyicisinde arayüz hatası | Olaylar yerel iş parçacığında gelir; MainThread.BeginInvokeOnMainThread. |
| Android derlemesinde "belirsizlik" Kotlin hatası | Eski build/native Gradle önbelleği; silip yeniden derleyin. |
RequestPermissionAsync hep false | Android 13+'ta izin reddedildi (fallbackToSettings: true); iOS'ta Push yeteneği eksik. Diğer belirtiler: Android, iOS. |
Cordova SDK
cordova-plugin-pushizo — Android ve iOS yerel SDK'larını cordova.exec köprüsüyle saran eklenti; push, in-app, bildirim kutusu, tercihler.
Unity SDK
com.pushizo.unity — Android ve iOS yerel SDK'larını saran UPM paketi (Unity 2021.3+); push, in-app, bildirim kutusu, tercihler, otomatik iOS/Android derleme ayarları.