Pushizo Docs
SDK rehberleri

.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.

HedefDavranış
net8.0-android, net9.0-androidYerel Android SDK'sı (minSdk 23)
net8.0-ios, net9.0-iosYerel 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

  1. Firebase konsolundan google-services.json indirip projeye ekleyin:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
  <GoogleServicesJson Include="Platforms/Android/google-services.json" />
</ItemGroup>
  1. Dashboard → Kanallar → Android Push → Firebase servis hesabı JSON'u.
  2. POST_NOTIFICATIONS, FCM servisi ve bildirim Activity'si yerel SDK manifestinden birleşir.
  3. UsePushizo izin sonucunu yaşam döngüsü olayından otomatik alır. Yalnızca Pushizo.Initialize kullanıyorsanız MainActivity içinde:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    PushizoAndroid.OnRequestPermissionsResult(requestCode);
}

iOS

  1. Platforms/iOS/Entitlements.plist içinde aps-environment, Info.plist içinde UIBackgroundModes → remote-notification.
  2. Dashboard → Kanallar → iOS Push → .p8 anahtarı.
  3. 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);
  1. Zengin medya, rozet ve teslimat onayı için Xcode'da Notification Service Extension hedefi ekleyip yerel PushizoExtension (SPM) ya da Pushizo/Extension (CocoaPods) ile PushizoNotificationServiceExtension sınıfını kullanın; rozet paylaşımı için IosAppGroup. 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ı adresler

Kullanı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, DidDismiss

Mesajlar 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 | Debug

Hata kodları

Bildirim kutusu ve tercih hataları PushizoException.Code ile gelir:

KodAnlam
NOT_READYAbonelik/kullanıcı kaydı henüz tamamlanmadı.
INVALID_ARGUMENTYerel SDK girdiyi reddetti.
PLATFORM_NOT_SUPPORTEDAndroid/iOS dışı hedef (Windows, MacCatalyst).
INVALID_RESPONSEKö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-ios

Sorun giderme

BelirtiNeden / çözüm
InvalidOperationException: Önce Pushizo.Initialize çağrılmalıUsePushizo/Initialize çağrılmadan SDK kullanıldı.
Android'de izin sonucu gelmiyorUsePushizo yerine Initialize kullanılıyor ve PushizoAndroid.OnRequestPermissionsResult iletilmiyor.
iOS'ta abonelik oluşmuyorAppDelegate'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 falseAndroid 13+'ta izin reddedildi (fallbackToSettings: true); iOS'ta Push yeteneği eksik. Diğer belirtiler: Android, iOS.

Bu sayfada