Flow ve paywall olaylarını yönetme - Android
Bu kılavuz, satın alma, yenileme, ürün seçimi ve flow render işlemleri için event yönetimini kapsar. Ayrıca düğme işlemlerini de (flow’u kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için düğme eylemlerini yönetme kılavuzumuza bakın.
Flow Builder veya Paywall Builder ile yapılandırılmış flow’lar ve paywall’lar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak bu ekranlar, uygulamanızın yanıt verebileceği bazı olaylar üretir. Bu olaylar arasında buton tıklamaları (kapat butonları, URL’ler, ürün seçimleri vb.) ve satın alma işlemlerine ilişkin bildirimler yer alır. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.
Adapty SDK’nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall’ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren örnek uygulamalarımıza göz atın.
Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız AdaptyFlowEventListener metodlarını uygulayın.
Bazı durumlarda varsayılan davranışı korumak istiyorsanız, AdaptyFlowDefaultEventListener sınıfını genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz.
Aşağıda AdaptyFlowDefaultEventListener içindeki varsayılan değerler yer almaktadır.
Kullanıcı tarafından oluşturulan olaylar
Ürün seçimi
Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu method çağrılır:
public override fun onProductSelected(
product: AdaptyPaywallProduct,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Satın alma başlatıldı
Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır:
public override fun onPurchaseStarted(
product: AdaptyPaywallProduct,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu metot Observer modunda çağrılmaz. Ayrıntılar için Android - Observer modunda Paywall Builder paywalllarını sunma konusuna bakın.
Başarılı, iptal edilmiş veya beklemedeki satın alma
Satın alma başarılı olursa şu metot çağrılır:
public override fun onPurchaseFinished(
purchaseResult: AdaptyPurchaseResult,
product: AdaptyPaywallProduct,
context: Context,
) {
if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
context.getActivityOrNull()?.onBackPressed()
}Olay örnekleri (Genişletmek için tıklayın)
// Successful purchase
{
"purchaseResult": {
"type": "Success",
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
}
}
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
// Cancelled purchase
{
"purchaseResult": {
"type": "UserCanceled"
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
// Pending purchase
{
"purchaseResult": {
"type": "Pending"
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu durumda ekranı kapatmanızı öneririz.
Bu metot, Observer modunda çağrılmayacaktır. Ayrıntılar için Android - Observer modunda Paywall Builder paywalllarını sunma konusuna bakın.
Başarısız satın alma
Bir satın alma işlemi hata nedeniyle başarısız olursa bu metot çağrılır. Bu durum; Google Play Billing hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptallerinin onPurchaseFinished metodunu iptal edilmiş sonuçla tetiklediğini, beklemedeki ödemelerin ise bu metodu tetiklemediğini unutmayın.
public override fun onPurchaseFailure(
error: AdaptyError,
product: AdaptyPaywallProduct,
context: Context,
) {}Etkinlik örneği (Genişletmek için tıklayın)
{
"error": {
"code": "purchase_failed",
"message": "Purchase failed due to insufficient funds",
"details": {
"underlyingError": "Insufficient funds in account"
}
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu yöntem, Observer modunda çağrılmaz. Ayrıntılar için Android - Observer modunda Paywall Builder paywalllerini sunma konusuna bakın.
Web ödeme navigasyonu tamamlandı
Bu yöntem, belirli bir ürün için web paywall açma girişiminin ardından çağrılır. Hem başarılı hem de başarısız navigasyon girişimlerini kapsar:
public override fun onFinishWebPaymentNavigation(
product: AdaptyPaywallProduct?,
error: AdaptyError?,
context: Context,
) {}Parametreler:
| Parametre | Açıklama |
|---|---|
| product | Web paywallın açıldığı AdaptyPaywallProduct. null olabilir. |
| error | Web paywall navigasyonu başarısız olursa AdaptyError nesnesi; navigasyon başarılıysa null. |
Etkinlik örnekleri (Genişletmek için tıklayın)
// Successful navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": null
}
// Failed navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "web_navigation_failed",
"message": "Failed to open web paywall",
"details": {
"underlyingError": "Browser unavailable"
}
}
}Başarılı geri yükleme
Bir satın alma başarıyla geri yüklenirse, bu metot çağrılır:
public override fun onRestoreSuccess(
profile: AdaptyProfile,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
},
"subscriptions": [
{
"vendorProductId": "premium_monthly",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
]
}
}Kullanıcının gerekli accessLevel’a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için Abonelik durumu konusuna bakın.
Başarısız geri yükleme
Adapty.restorePurchases() başarısız olursa, bu metot çağrılır:
public override fun onRestoreFailure(
error: AdaptyError,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"error": {
"code": "restore_failed",
"message": "Purchase restoration failed",
"details": {
"underlyingError": "No previous purchases found"
}
}
}Abonelik yükseltme
Bir kullanıcı aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, bu metodu geçersiz kılarak yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. İki seçeneğiniz vardır:
- Mevcut aboneliği yeni olanıyla değiştirin:
public override fun onAwaitingPurchaseParams(
product: AdaptyPaywallProduct,
context: Context,
onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
onPurchaseParamsReceived(
AdaptyPurchaseParameters.Builder()
.withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
.build()
)
return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}- Her iki aboneliği de koru (yenisini ayrı olarak ekle):
public override fun onAwaitingPurchaseParams(
product: AdaptyPaywallProduct,
context: Context,
onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}Bu yöntemi geçersiz kılmazsanız, varsayılan davranış her iki aboneliği de aktif tutmaktır (AdaptyPurchaseParameters.Empty kullanımıyla eşdeğer).
Gerekirse ek satın alma parametreleri de ayarlayabilirsiniz:
AdaptyPurchaseParameters.Builder()
.withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // isteğe bağlı - mevcut aboneliği değiştirmek için
.withOfferPersonalized(true) // isteğe bağlı - kişiselleştirilmiş fiyatlandırma kullanılıyorsa
.build()Etkinlik örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_yearly",
"localizedTitle": "Premium Yearly",
"localizedDescription": "Premium subscription for 1 year",
"localizedPrice": "$99.99",
"price": 99.99,
"currencyCode": "USD"
},
"subscriptionUpdateParams": {
"replacementMode": "with_time_proration"
}
}Veri getirme ve render etme
Ürün yükleme hataları
Başlatma sırasında ürünleri iletmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir:
public override fun onLoadingProductsFailure(
error: AdaptyError,
context: Context,
): Boolean = falseEtkinlik örneği (Genişletmek için tıklayın)
{
"error": {
"code": "products_loading_failed",
"message": "Failed to load products from the server",
"details": {
"underlyingError": "Network timeout"
}
}
}true döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrarlar.
Render hataları
Arayüz render edilirken bir hata oluşursa, bu metot çağrılarak raporlanır:
public override fun onError(
error: AdaptyError,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"error": {
"code": "rendering_failed",
"message": "Failed to render flow interface",
"details": {
"underlyingError": "Invalid flow configuration"
}
}
}Normal koşullarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin.
Gezinti
Sistem geri düğmesi
Varsayılan olarak, bir flow sistem geri düğmesiyle veya geri hareketiyle kapatılamaz — kullanıcı, flow’dan yalnızca sizin tanımladığınız bir yol aracılığıyla çıkar; örneğin bir Close düğmesi veya builder’daki bir on_device_back eylemi. Sistem geri düğmesinin flow’u kapatmasını istiyorsanız, onBackPressed metodunu geçersiz kılın ve ana activity’nizin ya da fragment’ınızın bu basışı işlemesine izin vermek için false döndürün:
public override fun onBackPressed(context: Context): Boolean {
return false // let the host handle the back press (e.g. finish the activity or pop the fragment)
}Bu callback, yalnızca mevcut ekran için herhangi bir on_device_back eylemi yapılandırılmamışsa çağrılır — yapılandırılmış bir eylem öncelik alır ve dahili olarak işlenir. Geri tuşuna basma işlemini tüketmek için true, ana bileşenin kendi geri işleme mantığının çalışmasına izin vermek için false döndürün.
Ayrılmış olaylar
AdaptyFlowEventListener, flow’ların henüz kullanmadığı bazı işlevler için birkaç callback tanımlar. Bunları uygulamanıza gerek yok — AdaptyFlowDefaultEventListener zaten varsayılan olarak boş (no-op) uygulamalar sağlar.
| Method | Description |
|---|---|
| onAnalyticEvent | Flow’lardan gelen özel analitik etkinlikler için ayrılmıştır. Flow’lar henüz bu etkinlikleri kodunuza iletmediğinden, bunu uygulamanıza gerek yoktur. |
| onShowAppRate | Flow’lardan gelen uygulama değerlendirme istekleri için ayrılmıştır. Flow’lar henüz uygulama değerlendirme isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. |
| onShowRequestPermission | Flow’lardan gelen sistem izin istekleri (push bildirimleri veya kamera erişimi gibi) için ayrılmıştır. Flow’lar henüz izin isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. |
Bu kılavuz, satın almalar, geri yüklemeler, ürün seçimi ve paywall oluşturma için olay işlemeyi kapsar. Ayrıca düğme işlemeyi (paywallı kapatma, bağlantı açma vb.) de uygulamanız gerekir. Ayrıntılar için düğme eylemlerini işleme kılavuzumuza bakın.
Paywall Builder ile yapılandırılan paywalllar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamaları (kapat düğmeleri, URL’ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili işlemlerin bildirimlerini kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.
Bu kılavuz yalnızca Adapty SDK v3.0 veya üzerini gerektiren yeni Paywall Builder paywallları içindir.
Adapty SDK’nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall’ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren örnek uygulamalarımıza göz atın.
Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız AdaptyUiEventListener metodlarını uygulayın.
Bazı durumlarda varsayılan davranışı korumak istiyorsanız AdaptyUiDefaultEventListener’ı genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz.
Aşağıda AdaptyUiDefaultEventListener’daki varsayılan davranışlar yer almaktadır.
Kullanıcı tarafından oluşturulan olaylar
Ürün seçimi
Bir ürün satın alma için seçilirse (kullanıcı tarafından veya sistem tarafından), bu metot çağrılır:
public override fun onProductSelected(
product: AdaptyPaywallProduct,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Satın alma başlatıldı
Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır:
public override fun onPurchaseStarted(
product: AdaptyPaywallProduct,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu metot, Observer modunda çağrılmaz. Ayrıntılar için Android - Observer modunda Paywall Builder paywall’larını gösterme konusuna bakın.
Başarılı, iptal edilmiş veya beklemedeki satın alma
Satın alma başarılı olursa şu metot çağrılır:
public override fun onPurchaseFinished(
purchaseResult: AdaptyPurchaseResult,
product: AdaptyPaywallProduct,
context: Context,
) {
if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
context.getActivityOrNull()?.onBackPressed()
}Olay örnekleri (Genişletmek için tıklayın)
// Successful purchase
{
"purchaseResult": {
"type": "Success",
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
}
}
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
// Cancelled purchase
{
"purchaseResult": {
"type": "UserCanceled"
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
// Pending purchase
{
"purchaseResult": {
"type": "Pending"
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu durumda ekranı kapatmanızı öneririz.
Bu metot, Observer modunda çağrılmaz. Ayrıntılar için Android - Observer modunda Paywall Builder paywalllarını gösterme konusuna bakın.
Başarısız satın alma
Bir satın alma işlemi hata nedeniyle başarısız olursa, bu method çağrılır. Buna Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları dahildir. Kullanıcı iptalleri yerine onPurchaseFinished methodunu iptal edilmiş sonucuyla tetiklediğini ve bekleyen ödemelerin bu methodu tetiklemediğini unutmayın.
public override fun onPurchaseFailure(
error: AdaptyError,
product: AdaptyPaywallProduct,
context: Context,
) {}Etkinlik örneği (Genişletmek için tıklayın)
{
"error": {
"code": "purchase_failed",
"message": "Purchase failed due to insufficient funds",
"details": {
"underlyingError": "Insufficient funds in account"
}
},
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Bu metot Observer modunda çağrılmaz. Ayrıntılar için Android - Observer modunda Paywall Builder paywalllarını gösterme konusuna bakın.
Web ödeme navigasyonu tamamlandı
Bu metot, belirli bir ürün için web paywall açma girişiminin ardından çağrılır. Başarılı ve başarısız navigasyon denemeleri için de çalışır:
public override fun onFinishWebPaymentNavigation(
product: AdaptyPaywallProduct?,
error: AdaptyError?,
context: Context,
) {}Parametreler:
| Parametre | Açıklama |
|---|---|
| product | Web paywallın açıldığı AdaptyPaywallProduct. null olabilir. |
| error | Web paywall navigasyonu başarısız olduysa AdaptyError nesnesi; navigasyon başarılıysa null. |
Olay örnekleri (Genişletmek için tıklayın)
// Successful navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": null
}
// Failed navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "web_navigation_failed",
"message": "Failed to open web paywall",
"details": {
"underlyingError": "Browser unavailable"
}
}
}Başarılı geri yükleme
Bir satın alma işleminin geri yüklenmesi başarılı olursa, bu metot çağrılır:
public override fun onRestoreSuccess(
profile: AdaptyProfile,
context: Context,
) {}Etkinlik örneği (Genişletmek için tıklayın)
{
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
},
"subscriptions": [
{
"vendorProductId": "premium_monthly",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
]
}
}Kullanıcının gerekli accessLevel’a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için Abonelik durumu konusuna bakın.
Başarısız geri yükleme
Adapty.restorePurchases() başarısız olursa, şu metot çağrılır:
public override fun onRestoreFailure(
error: AdaptyError,
context: Context,
) {}Örnek olay (Genişletmek için tıklayın)
{
"error": {
"code": "restore_failed",
"message": "Purchase restoration failed",
"details": {
"underlyingError": "No previous purchases found"
}
}
}Abonelik yükseltme
Etkinlik örneği (Genişletmek için tıklayın)
{
"product": {
"vendorProductId": "premium_yearly",
"localizedTitle": "Premium Yearly",
"localizedDescription": "Premium subscription for 1 year",
"localizedPrice": "$99.99",
"price": 99.99,
"currencyCode": "USD"
},
"subscriptionUpdateParams": {
"replacementMode": "with_time_proration"
}
}Veri çekme ve render etme
Ürün yükleme hataları
Ürünleri başlatma sırasında geçirmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alacaktır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir:
public override fun onLoadingProductsFailure(
error: AdaptyError,
context: Context,
): Boolean = falseÖrnek olay (Genişletmek için tıklayın)
{
"error": {
"code": "products_loading_failed",
"message": "Failed to load products from the server",
"details": {
"underlyingError": "Network timeout"
}
}
}true döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrar eder.
Render hataları
Arayüz render edilirken bir hata oluşursa, bu yöntem çağrılarak bildirilir:
public override fun onRenderingError(
error: AdaptyError,
context: Context,
) {}Olay örneği (Genişletmek için tıklayın)
{
"error": {
"code": "rendering_failed",
"message": "Failed to render paywall interface",
"details": {
"underlyingError": "Invalid paywall configuration"
}
}
}Normal koşullarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin.