# ANDROID - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.208Z Total files: 41 --- # File: sdk-installation-android --- --- title: "Android SDK'yı yükle ve yapılandır" description: "Abonelik tabanlı uygulamalar için Android'e Adapty SDK kurulumuna ilişkin adım adım kılavuz." --- Adapty SDK, mobil uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: Bu modül, platformlar arası paywalllar kolayca oluşturmaya yarayan kullanıcı dostu, kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. AdaptyUI, core modülüyle birlikte otomatik olarak etkinleştirilir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywallların gösterilmesi, satın almaların yapılması ve diğer temel işlevler dahil olmak üzere tam kurulumu sergileyen [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) göz atın. ::: ## Gereksinimler \{#requirements\} Minimum SDK gereksinimi: `minSdkVersion 21` :::info Adapty, Google Play Billing Library 8.x sürümüne kadar uyumludur. Varsayılan olarak Adapty, Google Play Billing Library v.7.0.0 ile çalışır; ancak daha yeni bir sürümü zorlamak isterseniz [bağımlılığı manuel olarak ekleyebilirsiniz](https://developer.android.com/google/play/billing/integrate#dependency). ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} Bağımlılık kurulum yönteminizi seçin: - Standart Gradle: Bağımlılıkları **modül düzeyindeki** `build.gradle` dosyanıza ekleyin - Projeniz `.gradle.kts` dosyaları kullanıyorsa, bağımlılıkları modül düzeyindeki `build.gradle.kts` dosyanıza ekleyin - Versiyon katalogları kullanıyorsanız, bağımlılıkları `libs.versions.toml` dosyanıza ekleyin ve ardından `build.gradle.kts` içinde referans verin [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Android.svg?style=flat&logo=android)](https://github.com/adaptyteam/AdaptySDK-Android/releases) ```groovy showLineNumbers dependencies { ... implementation platform('io.adapty:adapty-bom:') implementation 'io.adapty:android-sdk' // Only add this line if you plan to use Paywall Builder implementation 'io.adapty:android-ui' } ``` ```kotlin showLineNumbers dependencies { ... implementation(platform("io.adapty:adapty-bom:")) implementation("io.adapty:android-sdk") // Only add this line if you plan to use Paywall Builder: implementation("io.adapty:android-ui") } ``` ```toml showLineNumbers //libs.versions.toml [versions] .. adaptyBom = "" [libraries] .. adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } adapty = { module = "io.adapty:android-sdk" } // Only add this line if you plan to use Paywall Builder: adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... implementation(platform(libs.adapty.bom)) implementation(libs.adapty) // Only add this line if you plan to use Paywall Builder: implementation(libs.adapty.ui) } ``` Bağımlılık çözümlenemiyorsa, Gradle betiklerinizde `mavenCentral()` bulunduğundan emin olun.
Nasıl ekleneceğine dair talimat Projenizde `settings.gradle` dosyasında `dependencyResolutionManagement` yoksa, üst düzey `build.gradle` dosyanızın repositories bölümünün sonuna şunu ekleyin: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` Aksi takdirde, `settings.gradle` dosyanızdaki `dependencyResolutionManagement` bölümünün `repositories` kısmına şunu ekleyin: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... mavenCentral() } } ```
:::important Adapty Android SDK 4.0 ön sürümdür. Gradle, dinamik sürüm aralıkları (`+` veya `latest.release` gibi) üzerinden ön sürüm sürümlerini seçmez; bu nedenle tam sürümü sabitlemeniz gerekir. `adapty-bom` sürümünü 4.0 ön sürümüne ayarlayın — örneğin `io.adapty:adapty-bom:4.0.0-beta.2` ya da `libs.versions.toml` dosyasında `adaptyBom = "4.0.0-beta.2"`. BOM, eşleşen `android-sdk` ve `android-ui` sürümlerini sizin için çözer. Bkz. [Adapty Android SDK'yı v4'e Taşıma](migration-to-android-sdk-v4). ::: ## Adapty SDK'nın Adapty modülünü etkinleştir \{#activate-adapty-module-of-adapty-sdk\} ### Temel kurulum \{#basic-setup\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK'nın uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. ```kotlin showLineNumbers // In your Application class class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ) } } ``` ```java showLineNumbers // In your Application class public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( getApplicationContext(), new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ); } } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `Adapty.activate` tamamlanmasını bekleyin. Tam sıra için [Android SDK'da çağrı sırası](android-sdk-call-order) bölümüne bakın. ::: Şimdi uygulamanızda paywall'ları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız [Paywall Builder hızlı başlangıç kılavuzunu](android-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız [özel paywall'lar için hızlı başlangıç kılavuzuna](android-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştir \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız AdaptyUI modülüne ihtiyacınız var. Core modülü etkinleştirdiğinizde otomatik olarak etkinleştirilir; başka bir şey yapmanıza gerek yoktur. ## Proguard'ı yapılandır \{#configure-proguard\} Uygulamanızı production ortamına almadan önce Proguard yapılandırmanıza `-keep class com.adapty.** { *; }` satırını ekleyin. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kayıt sistemini ayarlayın \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki seviyeleri kullanabilirsiniz: | Seviye | Açıklama | | :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | | `AdaptyLogLevel.NONE` | Hiçbir şey loglanmaz. Varsayılan değer | | `AdaptyLogLevel.ERROR` | Yalnızca hatalar loglanır | | `AdaptyLogLevel.WARN` | Hatalar ve SDK'dan gelen kritik hata oluşturmayan ancak dikkat edilmesi gereken mesajlar loglanır. | | `AdaptyLogLevel.INFO` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır. | | `AdaptyLogLevel.VERBOSE` | Hata ayıklama sırasında işe yarayabilecek ek bilgiler (fonksiyon çağrıları, API sorguları vb.) loglanır. | Adapty'yi yapılandırmadan önce uygulamanızda log seviyesini ayarlayabilirsiniz. ```kotlin showLineNumbers Adapty.logLevel = AdaptyLogLevel.VERBOSE //recommended for development and the first production release ``` ```java showLineNumbers Adapty.setLogLevel(AdaptyLogLevel.VERBOSE); //recommended for development and the first production release ``` #### Günlük sistemi mesajlarını yönlendirme \{#redirect-the-logging-system-messages\} Herhangi bir nedenle Adapty'den gelen mesajları kendi sisteminize göndermek veya bir dosyaya kaydetmek istiyorsanız, varsayılan davranışı geçersiz kılabilirsiniz: ```kotlin showLineNumbers Adapty.setLogHandler { level, message -> //handle the log } ``` ```java showLineNumbers Adapty.setLogHandler((level, message) -> { //handle the log }); ``` ### Veri politikaları \{#data-policies\} Adapty, açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz; ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşmayı devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. IP tabanlı özelliklere ihtiyaç duyulmadığında kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da gereksiz veri toplamayı azaltmak için bu parametreyi kullanın. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build(); ``` #### Reklam kimliği (Ad ID) toplama ve paylaşmayı devre dışı bırakma \{#disable-advertising-id-ad-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcının [reklam kimliği](https://support.google.com/googleplay/android-developer/answer/6048248) toplanmasını devre dışı bırakmak için `adIdCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi Play Store politikalarına uymak, reklam kimliği izin istemini tetiklemekten kaçınmak ya da uygulamanız reklam kimliğine dayalı attribution veya analiz gerektirmiyorsa kullanın. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build(); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, performansı artırmak ve ağ kullanımını azaltmak için varsayılan olarak medyayı (görsel ve video gibi) önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. `AdaptyUI.configureMediaCache` yöntemini kullanarak varsayılan önbellek boyutunu ve geçerlilik süresini değiştirebilirsiniz. Bu adım isteğe bağlıdır; bu yöntemi çağırmazsanız varsayılan değerler kullanılır (100 MB disk boyutu, 7 gün geçerlilik süresi). ```kotlin showLineNumbers val cacheConfig = MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(3.days) .build() AdaptyUI.configureMediaCache(cacheConfig) ``` ```java showLineNumbers MediaCacheConfiguration cacheConfig = new MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(TimeInterval.days(3)) .build(); AdaptyUI.configureMediaCache(cacheConfig); ``` **Parametreler:** | Parametre | Zorunluluk | Açıklama | |-------------------------|----------|-----------------------------------------------------------------------------| | diskStorageSizeLimit | isteğe bağlı | Diskteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer 100 MB'tır. | | diskCacheValidityTime | isteğe bağlı | Önbelleğe alınan dosyaların geçerli sayıldığı süre. Varsayılan değer 7 gündür. | :::tip `AdaptyUI.clearMediaCache(strategy)` kullanarak medya önbelleğini çalışma zamanında temizleyebilirsiniz. `strategy` parametresi `CLEAR_ALL` veya `CLEAR_EXPIRED_ONLY` olabilir. ::: ### Gizlenmiş hesap kimliklerini ayarlama \{#set-obfuscated-account-ids\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryolarında gizlenmiş hesap kimliklerini zorunlu kılar. Bu kimlikler, Google Play'in kullanıcı bilgilerini anonim tutarken satın alımları tanımlamasına yardımcı olur; bu durum özellikle sahtekarlığı önleme ve analitik açısından önem taşır. Uygulamanız hassas kullanıcı verileri işliyorsa ya da belirli gizlilik düzenlemelerine uymak zorundaysanız bu kimlikleri ayarlamanız gerekebilir. Gizlenmiş kimlikler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın alımları takip etmesini sağlar. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build(); ``` ### Adapty'yi özel bir process'te çalıştırma \{#run-adapty-in-a-custom-process\} Varsayılan olarak Adapty yalnızca uygulamanızın ana process'inde çalışabilir. Uygulamanız birden fazla process kullanıyorsa, Adapty'yi yalnızca bir kez başlatın; aksi takdirde beklenmedik davranışlar oluşabilir. Adapty'yi farklı bir process'te çalıştırmanız gerekiyorsa, bunu yapılandırmanızda belirtin: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build(); ``` Bu değeri ayarlamadan Adapty'yi başka bir process'te etkinleştirmeye çalışırsanız, SDK bir uyarı kaydeder ve etkinleştirmeyi atlar. ### Yerel access level'ları etkinleştirme \{#enable-local-access-levels\} Varsayılan olarak, Android'de [yerel access level'lar](local-access-levels) devre dışıdır. Etkinleştirmek için `withLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build(); ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Auto Backup yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmalarıyla birlikte gelir. Yedekleme kuralları tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirici `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ifadelerinden bahseden bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/sample_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` Bunu çözmek için şunları yapmanız gerekir: - Manifest birleştiriciye, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty ve diğer SDK'lardan gelen yedekleme kurallarını tek bir XML dosyasında (ya da Android 12+ için bir çift dosyada) birleştirin. #### 1. Manifest'inize `tools` namespace'ini ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} Henüz eklenmemişse, kök `` etiketine `tools` namespace'ini ekleyin: ```xml ... ``` #### 2. `` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Uygulamanızın `AndroidManifest.xml` dosyasında `` etiketini güncelleyin; böylece uygulamanız son değerleri sağlar ve manifest birleştirici, kütüphane değerlerini değiştirsin: ```xml ... ``` Herhangi bir SDK da `android:allowBackup` ayarlıyorsa, bunu `tools:replace` listesine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralları dosyaları oluşturun \{#3-create-merged-backup-rules-files\} `app/src/main/res/xml/` dizini altında, Adapty'nin kurallarını diğer SDK'lardan gelen kurallarla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümlerinde uyumluluğu sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri ayıklama kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" ``` **Android 11 ve altı için** (eski tam yedekleme içerik formatını kullanır): ```xml title="sample_backup_rules.xml" ``` Bu kurulumla: - Adapty'nin yedekleme dışı tutmaları (`AdaptySDKPrefs.xml`) korunur. - Diğer SDK'ların dışı tutmaları (örneğin, `appsflyer-data`) da uygulanır. - Manifest birleştirici, uygulamanızın yapılandırmasını kullanır ve çakışan yedekleme özelliklerinde artık hata vermez. #### Başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app\} Satın alma akışını başlatan Activity, varsayılan olmayan bir `launchMode` kullanıyorsa, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan geri döndüğünde Android bu Activity'yi hatalı biçimde yeniden oluşturabilir ya da yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına veya iptal edilmiş olarak işlenmesine yol açabilir. Satın almaların doğru çalışmasını sağlamak için, satın alma akışını başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın; diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma akışını başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml ``` --- # File: android-quickstart-paywalls --- --- title: "Android SDK'da Flow Builder ile satın alımları etkinleştirme" description: "Adapty Flow Builder ile uygulama içi satın alımları etkinleştirmek için hızlı başlangıç kılavuzu." --- Uygulama içi satın alımları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – ürünleri kullanıcılara sunan ekran dizileri; no-code Flow Builder ile oluşturulur. SDK bunları `getFlow` aracılığıyla alır. Arayüzü kendi kodunuzla oluşturmayı tercih ediyorsanız bunun yerine paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](android-quickstart-manual). - [**Placement'lar**](placements) – flow'ların uygulamanızda nerede ve ne zaman gösterileceği (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın almaları etkinleştirmek için size üç yöntem sunar. Uygulama gereksinimlerinize bağlı olarak birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [satın almaya hazır eksiksiz bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder; tüm karmaşık satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda kendisi halleder. | | Manuel oluşturulan paywall'lar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine de Adapty'den alırsınız. [Kılavuza](android-quickstart-manual) bakın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı sınırlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl hayata geçirileceğini göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, [Paywall'ları manuel olarak uygulama](android-quickstart-manual) bölümüne bakın. ::: Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Görüntüleyin, satın alma işlemlerini Adapty yönetsin**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butona tıkladığında bağlantıları açın veya flow'u kapatın. ## Başlamadan Önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Adapty Kontrol Paneli'nde [uygulamanızı Google Play'e bağlayın](initial-android). 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ürünleri ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'unuzu ekleyin](create-placement). 5. Uygulama kodunuza [Adapty SDK'yı yükleyin ve etkinleştirin](sdk-installation-android). Bu kılavuz Adapty Android SDK v4 API'lerini kullanmaktadır. :::tip Bu adımları tamamlamanın en hızlı yolu [hızlı başlangıç kılavuzunu](quickstart) takip etmek ya da [Developer CLI](developer-cli-quickstart) kullanarak flow'lar ve placement'lar oluşturmaktır. ::: ## 1. Flow'u alın \{#get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturduğunuz bir flow'u almak için şunları yapmanız gerekir: 1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın ve bir görünüm yapılandırmasına sahip olup olmadığını kontrol edin. 2. `getFlowConfiguration` metodunu kullanarak görünüm yapılandırmasını alın. Görünüm yapılandırması, flow'u görüntülemek için gereken UI öğelerini ve stil bilgilerini içerir. :::important Görünüm yapılandırmasını almak için Flow Builder'da **Show on device** geçişini açmanız gerekir. Aksi takdirde boş bir görünüm yapılandırması alırsınız ve flow görüntülenmez. ::: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> if (result is AdaptyResult.Success) { val flow = result.value if (!flow.hasViewConfiguration) { return@getFlow } AdaptyUI.getFlowConfiguration(flow) { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value } } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); if (!flow.hasViewConfiguration()) { return; } AdaptyUI.getFlowConfiguration(flow, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) configResult).getValue(); // use loaded configuration } }); } }); ``` ## 2. Flow'u göster \{#display-the-flow\} Artık flow yapılandırmanız hazır olduğunda, flow'unuzu görüntülemek için birkaç satır kod eklemeniz yeterlidir. Görsel flow'u cihaz ekranında gösterebilmek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın ya da doğrudan `AdaptyFlowView` oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, null, // products = null means auto-fetch eventListener, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, null, // products = null means auto-fetch eventListener, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, null, // products = null means auto-fetch eventListener ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //add to the view hierarchy if needed, or you receive it from xml ... flowView.showFlow(flowConfiguration, products, eventListener); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, view hiyerarşisine ekleyebilir ve cihaz ekranında görüntüleyebilirsiniz. :::tip Bir flow'un nasıl görüntüleneceğine ilişkin daha fazla ayrıntı için [kılavuzumuza](android-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetme \{#handle-button-actions\} Kullanıcılar flow içindeki butonlara tıkladığında, Android SDK satın alma, geri yükleme, flow'u kapatma ve bağlantı açma işlemlerini otomatik olarak gerçekleştirir. Ancak bazı butonların özel veya önceden tanımlanmış ID'leri vardır ve bu eylemler kodunuzda ele alınmalıdır. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, aşağıda kapat butonunun varsayılan davranışı gösterilmektedir. Bunu koda eklemeniz gerekmez, ancak gerekirse nasıl yapıldığını buradan görebilirsiniz. :::tip Buton [action'ları](android-handle-paywall-actions) ve [event'leri](android-handling-events) nasıl yöneteceğinizi anlatan kılavuzlarımızı okuyun. ::: ```kotlin showLineNumbers title="Kotlin" override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ```java showLineNumbers @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada görüntülenmeye hazır. Paywall üzerinden test satın alımı tamamlayabildiğinizden emin olmak için [Google Play Store'da satın alımlarınızı test edin](testing-on-android). Şimdi, doğru kullanıcılara paywall gösterdiğinizden veya ücretli özelliklere erişim sağladığınızdan emin olmak için [kullanıcıların access level'ını kontrol etmeniz](android-check-subscription-status) gerekir. ## Tam örnek \{#full-example\} Tüm bu adımları uygulamanızda nasıl bir araya getirebileceğiniz aşağıda gösterilmektedir. ```kotlin showLineNumbers title="Kotlin" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Adapty.getFlow("YOUR_PLACEMENT_ID") { flowResult -> if (flowResult is AdaptyResult.Success) { val flow = flowResult.value if (!flow.hasViewConfiguration) { // Use custom logic return@getFlow } AdaptyUI.getFlowConfiguration(flow) { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value val flowView = AdaptyUI.getFlowView( this, flowConfiguration, null, // products = null means auto-fetch object : AdaptyFlowDefaultEventListener() { override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Close -> { (context as? Activity)?.onBackPressed() } } } } ) setContentView(flowView) } } } } } } ``` ```java showLineNumbers public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Adapty.getFlow("YOUR_PLACEMENT_ID", flowResult -> { if (flowResult instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) flowResult).getValue(); if (!flow.hasViewConfiguration()) { // Use custom logic return; } AdaptyUI.getFlowConfiguration(flow, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) configResult).getValue(); AdaptyFlowView flowView = AdaptyUI.getFlowView( this, flowConfiguration, null, // products = null means auto-fetch new AdaptyFlowDefaultEventListener() { @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } } ); setContentView(flowView); } }); } }); } } ``` --- # File: android-check-subscription-status --- --- title: "Android SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Android uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriklere erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) bilgisini kontrol etmeniz gerekir. Bu makale, kullanıcılara paywall göstermeniz mi yoksa ücretli özelliklere erişim izni vermeniz mi gerektiğine karar vermek için profil durumuna nasıl erişeceğinizi gösterir. ## Abonelik durumunu al \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profilindeki [access level](access-level) bilgisini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verilerine ihtiyaç duyduğunuzda (ör. uygulama açılışında) veya zorla güncelleme yapmak istediğinizde `getProfile` çağrısı yapın. - Abonelik durumu değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** ayarlayın. ### Profili al \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### Abonelik güncellemelerini dinle \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek üzere `Adapty.setOnProfileUpdatedListener()` kullanın. Kullanıcının abonelik durumu değiştiğinde Adapty bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncel profil verisini saklayın; böylece uygulamanız genelinde ek ağ isteği yapmadan kullanabilirsiniz. ```kotlin class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true } } ``` ```java public class SubscriptionManager { private AdaptyProfile currentProfile; public SubscriptionManager() { // Listen for profile updates Adapty.setOnProfileUpdatedListener(profile -> { this.currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() public boolean hasAccess() { if (currentProfile == null) { return false; } AdaptyAccessLevel premiumAccess = currentProfile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); return premiumAccess != null && premiumAccess.isActive(); } } ``` :::note Adapty, uygulamanız başladığında profil güncelleme dinleyicisini otomatik olarak çağırır; cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sunar. ::: ## Profili paywall mantığıyla ilişkilendir \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim izni verme konusunda anında karar vermeniz gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım, uygulama açılışı, premium bölümlere girilmesi veya belirli içerikler gösterilmeden önce gibi senaryolarda kullanışlıdır. ```kotlin private fun initializePaywall() { loadPaywall { paywallView -> checkAccessLevel { result -> when (result) { is AdaptyResult.Success -> { if (!result.value && paywallView != null) { setContentView(paywallView) // Show paywall if no access } } is AdaptyResult.Error -> { if (paywallView != null) { setContentView(paywallView) // Show paywall if access check fails } } } } } } private fun checkAccessLevel(callback: ResultCallback) { Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val hasAccess = result.value.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true callback.onResult(AdaptyResult.Success(hasAccess)) } is AdaptyResult.Error -> { callback.onResult(AdaptyResult.Error(result.error)) } } } } ``` ```java private void initializePaywall() { loadPaywall(paywallView -> { checkAccessLevel(result -> { if (result instanceof AdaptyResult.Success) { boolean hasAccess = ((AdaptyResult.Success) result).getValue(); if (!hasAccess && paywallView != null) { setContentView(paywallView); // Show paywall if no access } } else if (result instanceof AdaptyResult.Error) { if (paywallView != null) { setContentView(paywallView); // Show paywall if access check fails } } }); }); } private void checkAccessLevel(ResultCallback callback) { Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyAccessLevel premiumAccess = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); boolean hasAccess = premiumAccess != null && premiumAccess.isActive(); callback.onResult(AdaptyResult.success(hasAccess)); } else if (result instanceof AdaptyResult.Error) { callback.onResult(AdaptyResult.error(((AdaptyResult.Error) result).getError())); } }); } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların ödedikleri içeriklere erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](android-quickstart-identify) öğrenin. --- # File: android-quickstart-identify --- --- title: "Android SDK'da kullanıcıları tanımlama" description: "Android'de uygulama içi abonelik yönetimi için Adapty'yi kurmanın hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa sizin için hazırlanmıştır. Burada, Adapty'deki kullanıcı profilleriyle mevcut kimlik doğrulama sisteminizi nasıl uyumlu hale getireceğinizi öğreneceksiniz. ::: Kullanıcı satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline göre değişir: - Uygulamanız backend kimlik doğrulaması kullanmıyorsa ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılarla ilgili bölüme](#anonymous-users) bakın. - Uygulamanızda backend kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılarla ilgili bölüme](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmadan)** veya tanımlanmış **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi iç kimlik doğrulama sisteminizle eşleştirmek için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar şunlardır: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |-------------------------|-------------------------------------------------------|---------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar genelinde aynı profil | | **Veri sürekliliği** | Anonim kullanıcı verileri uygulama kurulumuna bağlıdır | Tanımlanmış kullanıcı verileri uygulama kurulumları arasında devam eder | ## Anonim kullanıcılar \{#anonymous-users\} Backend kimlik doğrulamanız yoksa **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profiliyle ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **etkinleştirme sırasında yeni bir anonim profil oluşturur**. 4. Kullanıcı uygulamanızda daha önce satın alma yapmışsa, varsayılan olarak satın almaları SDK etkinleştirmesinde App Store'dan otomatik olarak senkronize edilir. Yani anonim kullanıcılarda her kurulumda yeni profil oluşturulur; ancak bu bir sorun değildir çünkü Adapty analizinde [yeni kurulum olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için kurulumları **cihaz kimliklerine** göre saymanız gerekir. Bu durumda, yeniden kurulumlar dahil olmak üzere bir cihazdaki her uygulama kurulumu bir kurulum olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamada kullanıcıları tanımlamak için iki seçeneğiniz vardır: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğruladıklarında `identify()` metodunu customer user ID ile çağırın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başladığında zaten bir customer user ID'niz varsa, `activate()` çağrısında gönderin. :::important Varsayılan olarak, Adapty halihazırda başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; böylece her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Daha fazla ayrıntı için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başladıktan sonra tanımlıyorsanız (örneğin uygulamanıza giriş yaptıktan veya kayıt olduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty bunu otomatik olarak mevcut profile bağlar. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır. Parametre değerini sabit kodlarsanız, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir. ::: Diğer SDK metodlarını çağırmadan önce `identify` tamamlanma callback'inin tetiklenmesini bekleyin. Eş zamanlı çağrılar, tanımlanmış profil yerine anonim profile düşebilir. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Her kullanıcı için benzersiz if (error == null) { // başarılı identify } } ``` ```java showLineNumbers // Kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // başarılı identify } }); ``` ### SDK etkinleştirmesi sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` metodunu ayrıca çağırmak yerine `activate` metodunda gönderebilirsiniz. Customer user ID'yi bilmenize rağmen yalnızca etkinleştirmeden sonra ayarlarsanız, etkinleştirme sırasında Adapty yeni bir anonim profil oluşturacak ve `identify` metodunu çağırdıktan sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane iletebilirsiniz. Yeni bir tane iletirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID'ye bağlanır. :::note Varsayılan olarak, anonim profil oluşturma analiz panolarını etkilemez çünkü kurulumlar cihaz kimliklerine göre sayılır. Bir cihaz kimliği, cihazdaki mağazadan yapılan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, bunun ilk mi yoksa tekrarlanan bir kurulum mu olduğuna veya mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturmak (SDK etkinleştirmesinde veya çıkış yapıldığında), oturum açmak veya uygulamayı yeniden yüklemeden yükseltmek ek kurulum olayları oluşturmaz. Kurulumları cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) seçeneğini yapılandırın. ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build(); ``` ### Kullanıcı oturumunu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir düğmeniz varsa, `logout` metodunu kullanın. :::important Kullanıcı oturumunun kapatılması, kullanıcı için yeni bir anonim profil oluşturur. ::: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` :::info Kullanıcıları tekrar uygulamaya giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın alma izni verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıktan sonra erişimlerini koruduklarından emin olmanız gerekir: 1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil kimliğine bağlar. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin satın alma kayıt öncesinde yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), profil geçişinden sonra gerçek access level'ı almanız gerekir. Tanımlamadan hemen sonra [`getProfile`](android-check-subscription-status) metodunu çağırabilir veya verilerin otomatik olarak senkronize olması için [profil güncellemelerini dinleyebilirsiniz](android-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını hayata geçirdiniz! Uygulamanızın monetizasyonunda başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboarding'ler**](android-onboardings): Onboarding'lerle kullanıcıları etkileyin ve elde tutmayı artırın - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analiz hizmetleriyle entegre olun - [**Özel profil özellikleri belirleme**](android-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segment'ler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-android --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Android uygulamanıza entegre edin" description: "Android uygulamanıza Adapty SDK'sını uçtan uca entegre etmek için adapty-sdk-integration becerisini AI kodlama aracınızla kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu özellik beta aşamasındadır. Takılırsa veya beklenmedik şekilde davranırsa, bunun yerine [adım adım entegrasyon kılavuzunu](adapty-cursor-android) izleyin — yapay zeka aracınıza her aşamada doğru dokümanlarla rehberlik eder. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-android --- --- title: "Adapty'yi Android uygulamanıza AI yardımıyla entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi Android uygulamanıza adım adım entegre etme kılavuzu." --- Bu kılavuz, bir yapay zeka kodlama aracıyla Adapty'yi Android uygulamanıza adım adım entegre etmenizi sağlar; doğru Adapty dokümanlarını doğru sırayla besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı yapılandırmalar gerektirir. Bunu etkileşimli bir LLM becerisini kullanarak ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywall'larınızı ve placement'larınızı doğrudan Kontrol Panelini açmadan ayarlamasını sağlar. Yalnızca [mağazanızı bağlamanız](integrate-payments) Kontrol Paneli üzerinden yapılması gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra, agent'ınızda `/adapty-cli` komutunu çalıştırın. Her adımda — mağazanızı bağlamak için Kontrol Panelini açmanız gereken anlar dahil — sizi yönlendirecektir. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin yerinize bulamaz — bunları kendiniz sağlamanız gerekir. 1. **App store bağlantısı kurun**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Satın almaların çalışması için bu zorunludur. [Google Play'i bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin ve **API keys** bölümünü bulun. Kodda bu, Adapty yapılandırma builder'ına geçirdiğiniz string'dir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere kodda doğrudan başvurmazsınız — Adapty bunları paywall'lar aracılığıyla iletir. [Ürün ekleyin](quickstart-products) 4. **Bir paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasından bir paywall oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `Adapty.getPaywall("YOUR_PLACEMENT_ID")` çağrısına geçirdiğiniz string'dir. [Paywall oluşturun](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde her ürün için **Products** sayfasından yapılandırın. Kodda bu, `profile.accessLevels["premium"]?.isActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için uygundur. Ödeme yapan kullanıcılar ürüne bağlı olarak farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), koda başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Bu beşine sahip olduğunuzda, kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodu üretebilir. ::: ### Hazır olduğunuzda kurun \{#set-up-when-ready\} Bunlar kod yazmaya başlamak için zorunlu değil, ancak entegrasyon olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## Adapty dokümanlarını LLM'inize gönderin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi kullanın (önerilen) \{#use-context7-recommended\} [Context7](https://context7.com), LLM'inize güncel Adapty dokümantasyonuna doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, sorduklarınıza göre doğru dokümanları otomatik olarak çeker — manuel URL yapıştırmanıza gerek yoktur. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurmak için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, prompt'larınızda Adapty kütüphanesine başvurun: ``` Use the adaptyteam/adapty-docs library to look up how to install the Android SDK ``` :::warning Context7, doküman bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalıştığından emin olmak için aşağıdaki [uygulama adım adım rehberini](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Herhangi bir Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** butonuna tıklayın. Örneğin: [adapty-cursor-android.md](https://adapty.io/docs/tr/adapty-cursor-android.md). Aşağıdaki [uygulama adım adım rehberindeki](#implementation-walkthrough) her aşama, yapıştırmanız için `.md` bağlantıları içeren bir "LLM'inize gönderin" bloğu içerir. Aynı anda daha fazla dokümantasyon için aşağıdaki [index dosyaları ve platforma özgü alt kümeler](#plain-text-doc-index-files) bölümüne bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, uygulama sırasına göre Adapty entegrasyonunu ele alır. Her aşamada LLM'inize gönderilecek dokümanlar, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar yer alır. ### Entegrasyonunuzu planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), herhangi bir kod yazmadan önce LLM'in hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize hangi satın alma yaklaşımını kullandığınızı söyleyin — bu, takip etmesi gereken rehberleri etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin kodsuz builder'ında paywall'lar oluşturursunuz ve SDK bunları otomatik olarak gösterir. - [**Manuel olarak oluşturulan paywall'lar**](android-making-purchases): Kendi paywall arayüzünüzü kodla oluşturursunuz, ancak ürünleri çekmek ve satın almaları yönetmek için yine de Adapty kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](android-quickstart-paywalls) okuyun. ### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\} Android Studio'da Gradle aracılığıyla Adapty SDK bağımlılığını ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temeldir — bu olmadan hiçbir şey çalışmaz. **Rehber:** [Adapty SDK'yı yükleyin ve yapılandırın](sdk-installation-android) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-android.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Uygulama derlenir ve çalışır. Logcat'te Adapty etkinleştirme logu görünür. - **Dikkat:** "Public API key is missing" → App settings'den gerçek anahtarınızla yer tutucuyu değiştirdiğinizi kontrol edin. ::: ### Paywall'ları gösterin ve satın almaları yönetin \{#show-paywalls-and-handle-purchases\} Placement ID'ye göre bir paywall çekin, gösterin ve satın alma olaylarını yönetin. İhtiyacınız olan rehberler, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerlerken sandbox'ta test edin — sonuna kadar beklemeyin. Kurulum talimatları için [Sandbox'ta satın almaları test etme](test-purchases-in-sandbox) sayfasına bakın. **Rehberler:** - [Paywall'ları kullanarak satın almaları etkinleştirin (hızlı başlangıç)](android-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını çekin](android-get-pb-paywalls) - [Paywall'ları gösterin](android-present-paywalls) - [Paywall olaylarını yönetin](android-handling-events) - [Buton eylemlerine yanıt verin](android-handle-paywall-actions) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-paywalls.md - https://adapty.io/docs/tr/android-get-pb-paywalls.md - https://adapty.io/docs/tr/android-present-paywalls.md - https://adapty.io/docs/tr/android-handling-events.md - https://adapty.io/docs/tr/android-handle-paywall-actions.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma diyalogunu açar. - **Dikkat:** Boş paywall veya `getPaywall` hatası → placement ID'nin kontrol paneliyle tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: **Rehberler:** - [Özel paywall'ınızda satın almaları etkinleştirin (hızlı başlangıç)](android-quickstart-manual) - [Paywall'ları ve ürünleri çekin](fetch-paywalls-and-products-android) - [Remote config ile tasarlanmış paywall'ı gösterin](present-remote-config-paywalls-android) - [Satın alma yapın](android-making-purchases) - [Satın almaları geri yükleyin](android-restore-purchase) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-android.md - https://adapty.io/docs/tr/present-remote-config-paywalls-android.md - https://adapty.io/docs/tr/android-making-purchases.md - https://adapty.io/docs/tr/android-restore-purchase.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Özel paywall'ınız, Adapty'den çekilen ürünleri gösterir. Bir ürüne dokunmak sandbox satın alma diyalogunu açar. - **Dikkat:** Boş ürün dizisi → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitlesi olduğunu doğrulayın. ::: **Rehberler:** - [Observer mode genel bakış](observer-vs-full-mode) - [Observer mode'u uygulayın](implement-observer-mode-android) - [Observer mode'da işlemleri bildirin](report-transactions-observer-mode-android) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-android.md - https://adapty.io/docs/tr/report-transactions-observer-mode-android.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızla sandbox satın alması yapıldıktan sonra işlem, Adapty kontrol panelindeki **Event Feed**'de görünür. - **Dikkat:** Olay yok → Adapty'ye işlem bildirdiğinizi ve Google Play Real-Time Developer Notifications'ın yapılandırıldığını doğrulayın. ::: ### Abonelik durumunu kontrol edin \{#check-subscription-status\} Satın alma sonrasında, premium içeriği kilitlemek için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin. **Rehber:** [Abonelik durumunu kontrol edin](android-check-subscription-status) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın alması sonrasında `profile.accessLevels["premium"]?.isActive` değeri `true` döner. - **Dikkat:** Satın alma sonrası `accessLevels` boş → ürünün kontrol panelinde bir access level'a atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Satın almaların cihazlar arasında kalıcı olması için uygulama kullanıcı hesaplarınızı Adapty profilleriyle ilişkilendirin. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Rehber:** [Kullanıcıları tanımlayın](android-quickstart-identify) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-identify.md ``` :::tip[Kontrol Noktası] - **Beklenen:** `Adapty.identify("your-user-id")` çağrısından sonra, kontrol panelinin **Profiles** bölümünde özel kullanıcı ID'niz görünür. - **Dikkat:** Anonim profil atıfını önlemek için `identify`'ı, aktivasyondan sonra ancak paywall'ları çekmeden önce çağırın. ::: ### Yayın için hazırlanın \{#prepare-for-release\} Entegrasyonunuz sandbox'ta çalışır hale geldikten sonra, her şeyin canlı ortama hazır olduğundan emin olmak için yayın kontrol listesini inceleyin. **Rehber:** [Yayın kontrol listesi](release-checklist) LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Tüm kontrol listesi öğeleri onaylandı: mağaza bağlantısı, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Google Play Real-Time Developer Notifications eksik → **App settings → Android SDK** bölümünden yapılandırın, aksi takdirde olaylar kontrol panelinde görünmez. ::: ## Düz metin dokümantasyon index dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty dokümantasyonunu listeleyen veya birleştiren index dosyalarına sahibiz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı AI agent'ları için (ör. ChatGPT) `llms.txt` dosyasını indirip sohbete dosya olarak yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hali. Çok büyük — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Android'e özgü [`android-llms.txt`](https://adapty.io/docs/tr/android-llms.txt) ve [`android-llms-full.txt`](https://adapty.io/docs/tr/android-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: android-get-pb-paywalls --- --- title: "Flow ve paywall'ları getir - Android" description: "Android uygulamanızda Adapty'den flow ve paywall'ları çekin." --- [flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda görüntüleyebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'ı ve görünüm yapılandırmasını almaktır. :::tip 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](sample-apps) göz atın. :::
Uygulamanızda flow'ları görüntülemeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-android) yükleyin.
## Flow/paywall getirme \{#fetch-flowpaywall\} Bir flow veya paywall'ı Flow Builder ya da Paywall Builder kullanarak tasarladıysanız, kullanıcıya göstermek için mobil uygulama kodunuzda bunu render etme konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. Bununla birlikte, placement üzerinden ID'sini, görünüm yapılandırmasını almanız ve ardından onu mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, flow veya paywall'ı ve [görünüm yapılandırmasını](android-get-pb-paywalls#fetch-the-view-configuration) mümkün olduğunca erken almanız kritik öneme sahiptir; bu sayede kullanıcıya gösterilmeden önce görsellerin indirilmesi için yeterli zaman tanınmış olur. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```kotlin showLineNumbers ... Adapty.getFlow("YOUR_PLACEMENT_ID", loadTimeout = 10.seconds) { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow/paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers ... Adapty.getFlow("YOUR_PLACEMENT_ID", TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow/paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmesi için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir; ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında ağ isteklerini önlemek amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK, flow'ları ve paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Ayrıca daha hızlı getirmek için CDN ve CDN'e ulaşılamadığı durumlarda bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en son sürümü aldığınızdan emin olmak için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, bu metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`; burada `.seconds`, `import com.adapty.utils.seconds`'tan gelir) ya da `TimeInterval.seconds(5)` şeklinde kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, remote config'ler ve flow'un bir görünüm yapılandırması içerip içermediğini belirten `hasViewConfiguration` bayrağını barındıran bir `AdaptyFlow` nesnesi. Ön yükleme, özel UI veya programatik kontroller için gerçek ürünleri çekmek üzere `getPaywallProducts(flow)` çağrısını kullanın. | ## View konfigürasyonunu alma \{#fetch-the-view-configuration\} Flow veya paywall'ı aldıktan sonra, `flow.hasViewConfiguration` ile bir view konfigürasyonu içerip içermediğini kontrol edin. Bu bayrak, placement'ın Adapty Kontrol Paneli'nde nasıl tasarlandığını ayırt eder: - **`true`** — placement, **Flow Builder** (bir flow) veya **Paywall Builder** (bir paywall) ile tasarlanmış. Adapty, arayüzü sizin için render eder. Görünüm yapılandırmasını almak ve [flow veya paywall'ı sunmak](android-present-paywalls) için aşağıdaki adımlara devam edin. - **`false`** — placement, Builder arayüzü olmayan özel bir paywall. [Remote config paywall olarak ele alın](present-remote-config-paywalls-android). :::important Flow Builder'da **Show on device** geçişinin etkinleştirildiğinden emin olun. Bu seçenek açık değilse görünüm yapılandırması alınamaz. ::: Görünüm yapılandırmasını yüklemek için `getFlowConfiguration` metodunu kullanın. ```kotlin showLineNumbers if (!flow.hasViewConfiguration) { // use your custom logic return } AdaptyUI.getFlowConfiguration(flow, loadTimeout = 10.seconds) { result -> when(result) { is AdaptyResult.Success -> { val flowConfiguration = result.value // use loaded configuration } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **locale** |

isteğe bağlı

varsayılan: cihaz dili

| [Yerelleştirmenin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı; `-` ile ayrılmış bir veya iki alt etiket içeren dil kodu olarak beklenir (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve dil kodları](android-localizations-and-locale-codes). | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metod, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir; zira işlem arka planda farklı isteklerden oluşuyor olabilir. |
Görünüm yapılandırmasını yüklemek için `getFlowConfiguration` metodunu kullanın. ```java showLineNumbers if (!flow.hasViewConfiguration()) { // use your custom logic return; } AdaptyUI.getFlowConfiguration(flow, TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) result).getValue(); // use loaded configuration } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **locale** |

isteğe bağlı

varsayılan: cihaz dili

| Bir veya iki alt etiket içeren dil kodu formatında beklenen [yerelleştirme](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı; etiketler `-` ile ayrılır (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes). | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbellekteki veriler veya yerel yedek döndürülür. Nadir durumlarda bu metot, arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir. |
:::note Birden fazla dil kullanıyorsanız, [Builder yerelleştirmesinin nasıl ekleneceğini](add-paywall-locale-in-adapty-paywall-builder) ve yerel ayar kodlarının nasıl doğru kullanılacağını [buradan](android-localizations-and-locale-codes) öğrenin. ::: Yüklendikten sonra [flow veya paywall'ı gösterin](android-present-paywalls). ## Varsayılan kitle için bir flow veya paywall alarak daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında yüklenir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall yüklemek istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak çok önemlidir: önerilen yaklaşım, flow veya paywall'ı yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklanan `getFlow` metoduyla getirmektir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı flow'lar göstermeniz gerekiyorsa bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız gerekecek ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecek. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Eğer daha hızlı flow veya paywall yükleme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // the requested flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneririz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu senaryoda kullanıcılar en son veriye ulaşamayabilir; ancak internet bağlantısı ne kadar dengesiz olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizleme yapıldığında temizlendiğini unutmayın.

| ## Varlıkları özelleştir \{#customize-assets\} Flow veya paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görselleri ve videolarının önceden tanımlanmış kimlikleri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri kimliklerine göre hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir kimlik belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Bir video başlamadan önce önizleme görseli gösterin. İşte özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, ) ``` :::note Bir asset bulunamazsa, flow varsayılan görünümüne geri döner. ::: Videolar için, isteğe bağlı olarak bir `resolution` geçerek video yüklenmeden önce düzen alanını ayırabilir ve en boy oranını (`width / height`) belirleyebilirsiniz: ```kotlin showLineNumbers AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), resolution = AdaptyCustomVideoAsset.Resolution(width = 1080, height = 1920), ) ```
[Adapty Kontrol Paneli](adapty-paywall-builder)'nda yeni Paywall Builder ile [paywall'ınızın görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywall'ı ve görünüm yapılandırmasını almaktır. :::warning Yeni Paywall Builder, Android SDK 3.0 veya daha yüksek sürümüyle çalışır. ::: Paywall Builder ile özelleştirilmiş paywalllar için bu konuya başvurduğunuzu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywallları için paywallları ve ürünleri getirme](fetch-paywalls-and-products-android) konusuna bakın. :::tip 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](sample-apps) göz atın. :::
Mobil uygulamanızda paywallları görüntülemeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'unuzu ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-android) yükleyin.
## Paywall Builder ile tasarlanan paywallı getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem paywall içinde neyin gösterileceğini hem de nasıl gösterileceğini içerir. Yine de placement aracılığıyla ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, kullanıcıya göstermeden önce görsellerin indirilmesine yeterli süre tanımak amacıyla paywallı ve [görünüm yapılandırmasını](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız önemlidir. Paywall almak için `getPaywall` metodunu kullanın: ```kotlin showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en", loadTimeout = 10.seconds) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi ise bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu yaklaşımı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.

Adapty SDK, paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN ve CDN'e ulaşılamadığı durumlarda bağımsız bir yedek sunucu da kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywalllarınızın her zaman en son sürümünü almanızı garantilemek için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı işlevleriyle oluşturabilirsiniz (örneğin `5.seconds`, burada `.seconds` `import com.adapty.utils.seconds`'dan gelir) veya `TimeInterval.seconds(5)` şeklinde kullanabilirsiniz. Sınırlama koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | ## Paywall Builder ile tasarlanan paywallın görünüm yapılandırmasını getirme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm yapılandırması getirilemez. ::: Paywallı getirdikten sonra, bunun Paywall Builder ile oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywallı nasıl görüntüleyeceğiniz konusunda size yol gösterecektir. `ViewConfiguration` mevcutsa, bunu Paywall Builder paywallı olarak değerlendirin; aksi takdirde [remote config paywallı olarak işleyin](present-remote-config-paywalls). Görünüm yapılandırmasını yüklemek için `getViewConfiguration` metodunu kullanın. ```kotlin showLineNumbers if (!paywall.hasViewConfiguration) { // use your custom logic return } AdaptyUI.getViewConfiguration(paywall, loadTimeout = 10.seconds) { result -> when(result) { is AdaptyResult.Success -> { val viewConfiguration = result.value // use loaded configuration } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir. | Görünüm yapılandırmasını yüklemek için `getViewConfiguration` metodunu kullanın. ```java showLineNumbers if (!paywall.hasViewConfiguration()) { // use your custom logic return; } AdaptyUI.getViewConfiguration(paywall, TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyUI.LocalizedViewConfiguration viewConfiguration = ((AdaptyResult.Success) result).getValue(); // use loaded configuration } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesini](add-paywall-locale-in-adapty-paywall-builder) nasıl ekleyeceğinizi ve yerel ayar kodlarını doğru şekilde nasıl kullanacağınızı [buradan](android-localizations-and-locale-codes) öğrenin. ::: Yüklendikten sonra, [paywallı sunun](android-present-paywalls). ## Daha hızlı getirmek için varsayılan kitle paywallını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle paywalllar neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall göstermek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için paywallı getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Getirme](#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklanan `getPaywall` metoduyla paywallı getirmek olduğunu anlamak önemlidir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywalllarla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar, **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre) kaybettiğiniz anlamına gelir. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience` metodu Android SDK 2.11.3'ten itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi ise bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu yaklaşımı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.

| ## Varlıkları özelleştirme \{#customize-assets\} Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videoların önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Video başlamadan önce bir önizleme görseli gösterin. :::important Bu özelliği kullanmak için Adapty Android SDK'yı 3.7.0 veya daha yüksek bir sürüme güncelleyin. ::: Özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, customAssets, ) ``` :::note Bir varlık bulunamazsa, paywall varsayılan görünümüne geri döner. :::
--- # File: android-present-paywalls --- --- title: "Flow ve paywall'ları görüntüleme - Android" description: "Android uygulamanızda kullanıcılara flow ve paywall'ları sunun." --- Bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yok. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten barındırır. :::warning Bu kılavuz, Adapty tarafından render edilen flow'ları ve **yeni Paywall Builder paywalllarını** kapsar. Remote config paywallları ve [Observer mode](observer-vs-full-mode) için süreç farklıdır. - **Remote config paywall**'larını sunmak için bkz. [Remote config ile tasarlanmış paywall'ı göster](present-remote-config-paywalls). - **Observer mode paywall**'larını sunmak için bkz. [Android - Observer mode'da Paywall Builder paywall'larını sunma](android-present-paywall-builder-paywalls-in-observer-mode) ::: Aşağıda kullanılan `flowConfiguration` nesnesini almak için bkz. [Flow'ları ve paywall'ları al](android-get-pb-paywalls). Cihaz ekranında görsel flow'u görüntüleyebilmek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın veya `AdaptyFlowView`'ı doğrudan oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //gerekirse view hiyerarşisine ekleyin veya xml'den alın ... flowView.showFlow(flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra view hiyerarşisine ekleyebilir ve cihaz ekranında gösterebilirsiniz. `AdaptyFlowView`'ı `AdaptyUI.getFlowView()` çağrısı _yapmadan_ edinirseniz, ayrıca `.showFlow()` metodunu da çağırmanız gerekir. Görsel flow'u cihaz ekranında gösterebilmek için önce yapılandırmanız gerekir. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyFlowScreen( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------------------------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **flowConfiguration** | zorunlu | Flow'un görsel detaylarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi sağlayın. Yüklemek için `AdaptyUI.getFlowConfiguration(flow)` metodunu kullanın. Daha fazla bilgi için [Görünüm yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration) konusuna bakın. | | **products** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Flow olaylarını izlemek için bir `AdaptyFlowEventListener` sağlayın. Kullanım kolaylığı açısından `AdaptyFlowDefaultEventListener` sınıfını genişletmeniz önerilir. Daha fazla bilgi için [Flow ve paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı |

Inset'ler, tıklanabilir öğelerin sistem çubukların arkasına gizlenmesini önlemek için flow'un çevresindeki boşluklardır.

Varsayılan: `Unspecified` — yani Adapty inset'leri otomatik olarak ayarlar; bu, kenardan kenara flow'lar için idealdir.

Flow'unuz kenardan kenara değilse özel inset'ler ayarlamak isteyebilirsiniz. Bunun nasıl yapılacağını öğrenmek için aşağıdaki [Flow inset'lerini değiştirme](android-present-paywalls#change-flow-insets) bölümünü okuyun.

| | **customAssets** | isteğe bağlı | Flow veya paywall'ınızdaki görsel ve videoları çalışma zamanında değiştirmek için bir `AdaptyCustomAssets` nesnesi geçin. Daha fazla bilgi için [Varlıkları özelleştirme](android-get-pb-paywalls#customize-assets) konusuna bakın. | | **tagResolver** | isteğe bağlı | Flow metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve buna karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da özel etiketler konusuna bakın. | | **timerResolver** | isteğe bağlı | Özel zamanlayıcı işlevselliği kullanacaksanız çözümleyiciyi buraya geçin. | :::tip 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](sample-apps) göz atın. ::: ## Flow inset'lerini değiştirme \{#change-flow-insets\} Inset'ler, flow'un etrafındaki boşluklardır ve tıklanabilir öğelerin sistem çubuklarının arkasında gizlenmesini önler. Adapty varsayılan olarak inset'leri otomatik olarak ayarlar; bu, kenardan kenara flow'larda mükemmel çalışır. Flow'unuz kenardan kenara değilse, özel inset'ler ayarlamak isteyebilirsiniz: - `AdaptyFlowView` üst durum çubuğuyla da alt gezinme çubuğuyla da çakışmıyorsa `AdaptyFlowInsets.None` kullanın. - Flow'unuz üst durum çubuğuyla çakışıyor ancak altla çakışmıyorsa gibi daha özel durumlar için yalnızca `bottomInset` değerini aşağıdaki örnekte gösterildiği gibi `0` olarak ayarlayabilirsiniz: ```kotlin showLineNumbers //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view flowView.onReceiveSystemBarsInsets { insets -> val flowInsets = AdaptyFlowInsets.vertical(insets.top, 0) flowView.showFlow( flowConfiguration, products, eventListener, flowInsets, customAssets, tagResolver, timerResolver, ) } ``` ```java showLineNumbers ... ViewCompat.setOnApplyWindowInsetsListener(flowView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(flowView, null); AdaptyFlowInsets flowInsets = AdaptyFlowInsets.vertical(systemBarInsets.top, 0); flowView.showFlow(flowConfiguration, products, eventListener, flowInsets); return insets; }); ``` ## Geliştirici tanımlı zamanlayıcı kullanımı \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için bir `timerResolver` nesnesi oluşturun; bu nesne, özel zamanlayıcıları flow oluşturulduğunda yerlerine geçecek string değerlerle eşleştiren bir sözlük veya haritadır. İşte bir örnek: ```kotlin showLineNumbers ... val customTimers = mapOf( "CUSTOM_TIMER_NY" to Calendar.getInstance(TimeZone.getDefault()).apply { set(2025, 0, 1) }.time, // New Year 2025 ) val timerResolver = AdaptyUiTimerResolver { timerId -> customTimers.getOrElse(timerId, { Date(System.currentTimeMillis() + 3600 * 1000L) /* in 1 hour */ } ) } ``` ```java showLineNumbers ... Map customTimers = new HashMap<>(); customTimers.put( "CUSTOM_TIMER_NY", new Calendar.Builder().setTimeZone(TimeZone.getDefault()).setDate(2025, 0, 1).build().getTime() ); AdaptyUiTimerResolver timerResolver = new AdaptyUiTimerResolver() { @NonNull @Override public Date timerEndAtDate(@NonNull String timerId) { Date date = customTimers.get(timerId); return date != null ? date : new Date(System.currentTimeMillis() + 3600 * 1000L); /* in 1 hour */ } }; ``` Bu örnekte, `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı doğru değerle (örneğin `13d 09h 03m 34s` gibi — zamanlayıcının bitiş zamanından, yani Yılbaşı gibi bir tarihten, mevcut zamanın çıkarılmasıyla hesaplanan) dinamik olarak güncellemesini sağlar. ## Özel etiketleri kullanma \{#use-custom-tags\} Mobil uygulamanızda özel etiketler kullanmak için bir `tagResolver` nesnesi oluşturun; bu nesne, özel etiketleri flow oluşturulduğunda onların yerine geçecek string değerlerle eşleştiren bir sözlük ya da haritadır. İşte bir örnek: ```kotlin showLineNumbers val customTags = mapOf("USERNAME" to "John") val tagResolver = AdaptyUiTagResolver { tag -> customTags[tag] } ``` ```java showLineNumbers Map customTags = new HashMap<>(); customTags.put("USERNAME", "John"); AdaptyUiTagResolver tagResolver = customTags::get; ``` Bu örnekte, `USERNAME` Adapty kontrol panelinde `` olarak girdiğiniz özel bir etikettir. `tagResolver`, uygulamanızın bu özel etiketi dinamik olarak belirtilen değerle—örneğin `John`—değiştirmesini sağlar. `tagResolver`'ı flow'unuzu sunmadan hemen önce oluşturup doldurmanızı öneririz. Hazır olduğunda, flow'u sunmak için kullandığınız AdaptyUI metoduna iletin. ## Flow yükleme göstergesi rengini değiştirme \{#change-flow-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini aşağıdaki şekilde geçersiz kılabilirsiniz: ```xml showLineNumbers title = "XML" ```
Paywall Builder ile özelleştirilmiş bir paywall oluşturduysanız, kullanıcıya göstermek için mobil uygulama kodunuzda bu paywall'ı oluşturma konusunda endişelenmenize gerek yoktur. Böyle bir paywall, hem paywall içinde nelerin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz yalnızca SDK v3.0 gerektiren **yeni Paywall Builder paywallları** için geçerlidir. Paywall sunma süreci, farklı Paywall Builder sürümleriyle tasarlanan paywalllar, remote config paywalllar ve [Observer modu](observer-vs-full-mode) için farklılık gösterir. - **Remote config paywalllarını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls). - **Observer modu paywalllarını** sunmak için bkz. [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) ::: Aşağıda kullanılan `viewConfiguration` nesnesini almak için bkz. [Paywall Builder paywalllerini ve yapılandırmalarını getirme](android-get-pb-paywalls). Görsel paywall'ı cihaz ekranında göstermek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getPaywallView()` metodunu çağırın veya `AdaptyPaywallView`'i doğrudan oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //gerekirse görünüm hiyerarşisine ekleyin veya xml'den alın ... paywallView.showPaywall(viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver); ``` ```xml showLineNumbers ``` Görünüm başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyebilir ve cihaz ekranında gösterebilirsiniz. `AdaptyPaywallView`'ı `AdaptyUI.getPaywallView()` çağrısı _dışında_ bir yöntemle aldıysanız, `.showPaywall()` metodunu da çağırmanız gerekir. Görsel paywallı cihaz ekranında göstermek için önce yapılandırmanız gerekir. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :---------------------------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.LocalizedViewConfiguration` nesnesi sağlayın. Bunu yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywallın görsel yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **products** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı açısından AdaptyUiDefaultEventListener'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı |

Insets, tıklanabilir öğelerin sistem çubuklarının arkasına gizlenmesini önleyen paywall etrafındaki boşluklardır.

Varsayılan: `UNSPECIFIED` — bu, Adapty'nin inset'leri otomatik olarak ayarlayacağı anlamına gelir; bu ayar kenardan kenara paywalllar için mükemmel çalışır.

Paywallınız kenardan kenara değilse özel inset'ler ayarlamak isteyebilirsiniz. Bunun nasıl yapılacağını aşağıdaki [Paywall inset'lerini değiştirme](android-present-paywalls#change-paywall-insets) bölümünde okuyabilirsiniz.

| | **personalizedOfferResolver** | isteğe bağlı | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver` uygulayın ve `AdaptyPaywallProduct`'ı, ürünün fiyatı kişiselleştirilmişse `true`, değilse `false` olarak eşleyen kendi mantığınızı geçirin. | | **tagResolver** | isteğe bağlı | Paywall metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve bunu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'daki Özel Etiketler konusuna bakın. | | **timerResolver** | isteğe bağlı | Özel zamanlayıcı işlevselliği kullanacaksanız çözümleyiciyi buraya geçirin. | :::tip 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](sample-apps) göz atın. ::: ## Paywall insets'lerini değiştirme \{#change-paywall-insets\} Insets, tıklanabilir öğelerin sistem çubukları arkasında gizlenmesini engelleyen paywall etrafındaki boşluklardır. Varsayılan olarak Adapty, kenar-kenara paywalllar için harika çalışan insets'leri otomatik olarak ayarlar. Paywallınız kenar-kenara değilse özel insets ayarlamak isteyebilirsiniz: - `AdaptyPaywallView` ile ne durum çubuğu ne de gezinme çubuğu çakışmıyorsa `AdaptyPaywallInsets.NONE` kullanın. - Paywallınız üst durum çubuğuyla çakışıyor ama alt kısımla çakışmıyorsa gibi daha özel durumlarda, aşağıdaki örnekte gösterildiği gibi yalnızca `bottomInset`'i `0` olarak ayarlayabilirsiniz: ```kotlin showLineNumbers //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.vertical(insets.top, 0) paywallView.showPaywall( viewConfiguration, products, eventListener, paywallInsets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, 0); paywallView.showPaywall(paywall, products, viewConfiguration, paywallInsets, productTitleResolver); return insets; }); ``` ## Geliştirici tanımlı zamanlayıcı kullanma \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için bir `timerResolver` nesnesi oluşturun; bu nesne, özel zamanlayıcıları paywall oluşturulduğunda onların yerine geçecek string değerleriyle eşleştiren bir sözlük ya da haritadır. İşte bir örnek: ```kotlin showLineNumbers ... val customTimers = mapOf( "CUSTOM_TIMER_NY" to Calendar.getInstance(TimeZone.getDefault()).apply { set(2025, 0, 1) }.time, // New Year 2025 ) val timerResolver = AdaptyUiTimerResolver { timerId -> customTimers.getOrElse(timerId, { Date(System.currentTimeMillis() + 3600 * 1000L) /* in 1 hour */ } ) } ``` ```java showLineNumbers ... Map customTimers = new HashMap<>(); customTimers.put( "CUSTOM_TIMER_NY", new Calendar.Builder().setTimeZone(TimeZone.getDefault()).setDate(2025, 0, 1).build().getTime() ); AdaptyUiTimerResolver timerResolver = new AdaptyUiTimerResolver() { @NonNull @Override public Date timerEndAtDate(@NonNull String timerId) { Date date = customTimers.get(timerId); return date != null ? date : new Date(System.currentTimeMillis() + 3600 * 1000L); /* in 1 hour */ } }; ``` Bu örnekte, `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar; örneğin `13d 09h 03m 34s` (zamanlayıcının bitiş zamanı, Yeni Yıl günü gibi, eksi mevcut zaman olarak hesaplanır). ## Özel etiketleri kullanma \{#use-custom-tags\} Mobil uygulamanızda özel etiketler kullanmak için bir `tagResolver` nesnesi oluşturun; bu nesne, özel etiketleri paywall render edildiğinde onların yerini alacak dize değerleriyle eşleştiren bir sözlük veya haritadır. İşte bir örnek: ```kotlin showLineNumbers val customTags = mapOf("USERNAME" to "John") val tagResolver = AdaptyUiTagResolver { tag -> customTags[tag] } ``` ```java showLineNumbers Map customTags = new HashMap<>(); customTags.put("USERNAME", "John"); AdaptyUiTagResolver tagResolver = customTags::get; ``` Bu örnekte `USERNAME`, Adapty kontrol panelinde `` olarak girdiğiniz özel bir etikettir. `tagResolver`, uygulamanızın bu özel etiketi dinamik olarak belirtilen değerle (örneğin `John`) değiştirmesini sağlar. `tagResolver`'ı paywall'ı göstermeden hemen önce oluşturup doldurmanızı öneririz. Hazır olduğunda, paywall'ı sunmak için kullandığınız AdaptyUI metoduna aktarın. ## Yükleme göstergesinin rengini değiştirme \{#change-paywall-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini aşağıdaki şekilde geçersiz kılabilirsiniz: ```xml showLineNumbers title = "XML" ```
--- # File: android-handle-paywall-actions --- --- title: "Flow aksiyonlarına yanıt verme - Android" description: "Android uygulamanızda flow'lar ve paywall'lardan gelen buton aksiyonlarını yönetin." --- Adapty Flow Builder veya Paywall Builder kullanarak flow'lar veya paywall'lar oluşturuyorsanız, butonları doğru şekilde ayarlamak kritik öneme sahiptir: 1. [Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden tanımlanmış bir eylem atayın ya da özel bir eylem kimliği oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve önceden tanımlanmış eylemleri kodunuzda nasıl yöneteceğinizi gösterir. :::warning **Yalnızca satın almalar, yenileme işlemleri, flow/paywall kapatma ve URL açma otomatik olarak işlenir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun bir yanıt uygulaması gerektirir. ::: ## Flow ve paywallları kapatma \{#close-flows-and-paywalls\} Flow veya paywallınıza bir kapatma butonu eklemek için: 1. Builder'da bir buton ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda `close` eylemi için bir handler uygulayın. :::info Android SDK'da `close` eylemi, varsayılan olarak flow veya paywallı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda değiştirebilirsiniz. Örneğin, bir flow'un kapatılması başka bir flow'un açılmasını tetikleyebilir. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ## Flow ve paywalllardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde yönetin. ::: Flow veya paywallınızdan bir bağlantı açan bir düğme eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info Android SDK'da `openUrl` eylemi varsayılan olarak URL'yi açar. Ancak gerekirse bu davranışı kodunuzda değiştirebilirsiniz. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.OpenUrl -> { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(action.url)) // default behavior context.startActivity(intent) } } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yöneten bir buton eklemek için: 1. Builder'da bir buton ekleyin, ona **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi setiiniz veya tek seferlik satın almalarınız varsa, başka bir flow ya da paywall görüntüleyecek bir buton ekleyebilirsiniz: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Custom -> { if (action.customId == "openNewPaywall") { // Display another flow or paywall } } } } ``` Adapty paywall builder kullanarak paywall oluşturuyorsanız, düğmeleri doğru şekilde ayarlamak çok önemlidir: 1. [Paywall Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden var olan bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve önceden var olan eylemleri kodunuzda nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar, geri yüklemeler, paywall kapatmaları ve URL açma işlemleri otomatik olarak işlenir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun yanıt uygulaması gerektirir. ::: ## Paywallları kapatma \{#close-paywalls\} Paywallınızı kapatacak bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda, paywallı kapatan `close` eylemi için bir işleyici uygulayın. :::info Android SDK'da `close` eylemi, paywall'ı varsayılan olarak kapatır. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywallı kapatmak başka bir paywallın açılmasını tetikleyebilir. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle butonları işlediğiniz gibi yönetin. ::: Paywall'ınızdan bir bağlantı açan buton eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Paywall builder'da bir buton ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info Android SDK'da `openUrl` eylemi varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.OpenUrl -> { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(action.url)) // default behavior context.startActivity(intent) } } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` eylemi için bir işleyici uygulayın. ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Login -> { val intent = Intent(context, LoginActivity::class.java) context.startActivity(intent) } } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yönetecek bir düğme eklemek için: 1. Paywall Builder'da bir düğme ekleyin, **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, farklı bir abonelik teklifi grubunuz veya tek seferlik satın almalarınız varsa, başka bir paywall görüntüleyecek bir düğme ekleyebilirsiniz: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Custom -> { if (action.customId == "openNewPaywall") { // Display another paywall } } } } ``` --- # File: android-handling-events --- --- title: "Flow ve paywall olaylarını yönetme - Android" description: "Android uygulamanızda flow ve paywall olaylarını yönetin." --- :::important 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](android-handle-paywall-actions) bakın. ::: [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-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. :::tip 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](sample-apps) 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 \{#user-generated-events\} #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu method çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onProductSelected( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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ı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseStarted( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olursa şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" 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) ```javascript // 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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarısız satın alma \{#failed-purchase\} 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. ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFailure( error: AdaptyError, product: AdaptyPaywallProduct, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu yöntem, belirli bir ürün için [web paywall](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: ```kotlin showLineNumbers title="Kotlin" 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) ```javascript // 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 \{#successful-restore\} Bir satın alma başarıyla geri yüklenirse, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreSuccess( profile: AdaptyProfile, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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](android-listen-subscription-changes) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olursa, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreFailure( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
#### Abonelik yükseltme \{#upgrade-subscription\} 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: 1. **Mevcut aboneliği** yeni olanıyla değiştirin: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback, ): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived( AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) .build() ) return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` 2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle): ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback, ): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` :::note 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: ```kotlin 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) ```javascript { "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 \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} 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: ```kotlin showLineNumbers title="Kotlin" public override fun onLoadingProductsFailure( error: AdaptyError, context: Context, ): Boolean = false ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "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ı \{#rendering-errors\} Arayüz render edilirken bir hata oluşursa, bu metot çağrılarak raporlanır: ```kotlin showLineNumbers title="Kotlin" public override fun onError( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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 \{#navigation\} #### Sistem geri düğmesi \{#system-back-button\} 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: ```kotlin showLineNumbers title="Kotlin" 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 \{#reserved-events\} `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. |
:::important 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](android-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-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. :::warning Bu kılavuz yalnızca Adapty SDK v3.0 veya üzerini gerektiren **yeni Paywall Builder paywallları** içindir. ::: :::tip 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](sample-apps) 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 \{#user-generated-events\} #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçilirse (kullanıcı tarafından veya sistem tarafından), bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onProductSelected( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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ı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseStarted( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olursa şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" 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) ```javascript // 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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarısız satın alma \{#failed-purchase\} 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. ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFailure( error: AdaptyError, product: AdaptyPaywallProduct, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "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](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu metot, belirli bir ürün için [web paywall](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: ```kotlin showLineNumbers title="Kotlin" 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) ```javascript // 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 \{#successful-restore\} Bir satın alma işleminin geri yüklenmesi başarılı olursa, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreSuccess( profile: AdaptyProfile, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "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](android-listen-subscription-changes) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olursa, şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreFailure( error: AdaptyError, context: Context, ) {} ```
Örnek olay (Genişletmek için tıklayın) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
#### Abonelik yükseltme \{#upgrade-subscription\} 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 var: 1. **Mevcut aboneliği** yenisiyle değiştirin: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived( AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) .build() ) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` 2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle): ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` :::note Bu metodu override etmezseniz, varsayılan davranış her iki aboneliği de aktif tutmaktır (`AdaptyPurchaseParameters.Empty` kullanımına eşdeğer). ::: Gerekirse ek satın alma parametreleri de belirleyebilirsiniz: ```kotlin 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() ``` Yeni bir abonelik satın alınırken mevcut bir abonelik hâlâ aktifse, geçerli aboneliği yenisiyle değiştirmek için bu metodu override edin. Aktif abonelik etkin kalmaya devam etmeli ve yeni abonelik ayrı olarak eklenmeliyse `onSubscriptionUpdateParamsReceived(null)` çağırın: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingSubscriptionUpdateParams( product: AdaptyPaywallProduct, context: Context, onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, ) { onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) } ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "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 \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Ü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: ```kotlin showLineNumbers title="Kotlin" public override fun onLoadingProductsFailure( error: AdaptyError, context: Context, ): Boolean = false ```
Örnek olay (Genişletmek için tıklayın) ```javascript { "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ı \{#rendering-errors\} Arayüz render edilirken bir hata oluşursa, bu yöntem çağrılarak bildirilir: ```kotlin showLineNumbers title="Kotlin" public override fun onRenderingError( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "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.
--- # File: android-use-fallback-paywalls --- --- title: "Android - Yedek paywall'ları kullanma" description: "Kullanıcıların çevrimdışı olduğu veya Adapty sunucularının kullanılamadığı durumları yönetin." --- :::warning Yedek paywall'lar Android SDK v2.11 ve sonraki sürümlerde desteklenmektedir. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek yapılandırma dosyasını Android projenizin `assets` veya `res/raw` dizinine taşıyın. 2. Hedef flow, paywall veya onboarding'i getirmeden **önce** `.setFallback` metodunu çağırın. ```kotlin showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory val location = FileLocation.fromAsset("android_fallback.json") //or `FileLocation.fromAsset("/android_fallback.json")` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory val location = FileLocation.fromResId(context, R.raw.android_fallback) //you can also pass a file URI val fileUri: Uri = //get Uri for the file with fallback paywalls val location = FileLocation.fromFileUri(fileUri) //pass the file location Adapty.setFallback(location, callback) ``` ```java showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory FileLocation location = FileLocation.fromAsset("android_fallback.json"); //or `FileLocation.fromAsset("/android_fallback.json");` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory FileLocation location = FileLocation.fromResId(context, R.raw.android_fallback); //you can also pass a file URI Uri fileUri = //get Uri for the file with fallback paywalls FileLocation location = FileLocation.fromFileUri(fileUri); //pass the file location Adapty.setFallback(location, callback); ``` Parametreler: | Parametre | Açıklama | | :----------- | :----------------------------------------------------------- | | **location** | Yedek yapılandırma dosyası için [FileLocation](https://android.adapty.io/adapty/com.adapty.utils/-file-location/-companion/) nesnesi | --- # File: android-localizations-and-locale-codes --- --- title: "Android SDK'da yerelleştirme ve yerel ayar kodlarını kullanma" description: "Global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin (Android)." --- ## Bu neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır; örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywall'ı çekmeye çalışırken. Yerel ayar kodları karmaşık bir yapıya sahip olup platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlar için dahili bir standart kullanıyoruz. Ancak bu kodların karmaşıklığı nedeniyle, sunucumuza tam olarak ne gönderdiğinizi ve bundan sonra ne olacağını anlamanız son derece önemlidir; böylece her zaman beklediğiniz sonucu alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan yerel ayar koduyla birlikte bir çağrı aldığında ve bir paywall için karşılık gelen yerelleştirmeyi aramaya başladığında şunlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`), kısa çizgilerle (`-`) değiştirilir 2. Ardından tam olarak eşleşen yerel ayar koduna sahip yerelleştirme aranır 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesi döndürülür Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yol \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, büyük ihtimalle projenizde yerelleştirilmiş dize dosyalarıyla zaten çalışıyorsunuzdur. Bu durumda, her yerelleştirme için ilgili dosyalarınıza hedeflenen Adapty yerel ayar kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde kullanın: ```kotlin showLineNumbers // 1. Modify your strings.xml files /* strings.xml - Spanish */ es /* strings.xml - Portuguese (Brazil) */ pt-br // 2. Extract and use the locale code val localeCode = context.getString(R.string.adapty_paywalls_locale) // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yöntemle, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği üzerinde tam kontrol sahibi olursunuz. ## Yerelleştirmeleri uygulama: alternatif yol \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça yerel ayar kodları tanımlamadan benzer (ancak özdeş olmayan) sonuçlar elde edebilirsiniz. Bu, platforma ait başka nesnelerden yerel ayar kodu çıkarmak anlamına gelir: ```kotlin showLineNumbers val locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.resources.configuration.locales[0] else context.resources.configuration.locale val localeCode = locale.toLanguageTag() // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşımı önermiyoruz; çünkü Adapty sunucusunun tam olarak ne alacağını tahmin etmek güçtür. Yine de bu yaklaşımı kullanmaya karar verirseniz, tüm ilgili kullanım senaryolarını ele aldığınızdan emin olun. --- # File: android-web-paywall --- --- title: "Android SDK'da web paywall'larını uygulayın" description: "Play Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall'u ayarlayın." --- :::important Başlamadan önce [kontrol panelinde web paywall'unuzu yapılandırdığınızdan](web-paywall) ve Adapty SDK'nın 3.15 veya daha yeni bir sürümünü yüklediğinizden emin olun. ::: ## Web paywall'larını açma \{#open-web-paywalls\} Kendi geliştirdiğiniz bir paywall ile çalışıyorsanız, web paywall'larını SDK yöntemiyle ele almanız gerekir. `.openWebPaywall` yöntemi: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'u yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü takip eder ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` isteği gönderir. Bu sayede ödeme başarılı olmuş ve erişim hakları güncellenmiş ise abonelik uygulamada neredeyse anında etkinleşir. :::note Kullanıcılar uygulamaya döndükten sonra profil güncellemelerini yansıtmak için arayüzü yenileyin. Adapty, profil güncelleme olaylarını alıp işleyecektir. ::: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error } } ``` :::note `openWebPaywall` yönteminin iki versiyonu vardır: 1. Paywall'a göre URL oluşturan ve ürün verilerini de URL'lere ekleyen `openWebPaywall(product)`. 2. Paywall'a göre URL oluşturan ancak ürün verilerini URL'lere eklemeyen `openWebPaywall(paywall)`. Adapty paywall'undaki ürünler web paywall'undakilerden farklıysa bunu kullanın. ::: ## Uygulama içi tarayıcıda web paywall'larını açma \{#open-web-paywalls-in-an-in-app-browser\} Varsayılan olarak web paywall'lar harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sunmak için web paywall'larını uygulama içi tarayıcıda açabilirsiniz. Bu, web satın alma sayfasını uygulamanızın içinde göstererek kullanıcıların uygulama değiştirmeden işlemlerini tamamlamasına olanak tanır. Bunu etkinleştirmek için `presentation` parametresini `AdaptyWebPresentation.InAppBrowser` olarak ayarlayın: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, presentation = AdaptyWebPresentation.InAppBrowser, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error val adaptyError = error } } ``` --- # File: android-troubleshoot-paywall-builder --- --- title: "Android SDK'da Paywall Builder Sorunlarını Giderme" description: "Android SDK'da Paywall Builder sorunlarını giderme" --- Bu kılavuz, Android SDK'da Adapty Paywall Builder ile tasarlanmış paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `getViewConfiguration` metodu paywall yapılandırmasını alamıyor. **Neden**: Paywall Builder'da paywall'un cihazda görüntülenmesi etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. ## Paywall görüntüleme sayısı çok büyük \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntüleme sayısı beklenen değerin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (Android SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz; bu, Paywall Builder veya Flow Builder kullanıyorsanız görüntüleme sayısını çifte katlıyor. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitik otomatik olarak takip edilir, dolayısıyla bu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (Android SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder sorunlarıyla karşılaşıyorsunuz. **Çözüm**: Gerekirse [migration kılavuzlarını](android-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun daha yeni SDK sürümlerinde çözülmüştür. --- # File: android-quickstart-manual --- --- title: "Android SDK'da özel paywall'unuzda satın almaları etkinleştirin" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Android paywall'larınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall implementasyonunun tam kontrolü sizde kalırken Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler. :::important **Bu rehber, özel paywall'lar uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız [Adapty Flow Builder](android-quickstart-paywalls)'ı kullanın. Flow Builder ile no-code görsel editörde flow'lar oluşturursunuz, tüm satın alma mantığını Adapty otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlama \{#set-up-products\} Uygulama içi satın alımları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Products**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalls**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywall'lar aracılığıyla ulaşılabilir; bu tasarım sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. - [**Placements**](placements) – uygulamanızda paywall'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Paywall'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu yapı, A/B testleri çalıştırmayı ve farklı kullanıcılara farklı paywall'lar göstermeyi kolaylaştırır. Bu kavramları, özel paywallınızla çalışsanız bile anladığınızdan emin olun. Bunlar, uygulamanızda sattığınız ürünleri yönetmenin yollarından ibarettir. Özel paywallınızı hayata geçirmek için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu yapı, ürünlerinizi almanızı sağlar. Kontrol panelinde yapmanız gerekenleri anlamak için hızlı başlangıç kılavuzunu [buradan](quickstart) takip edin. ### Kullanıcıları yönetme \{#manage-users\} Kendi tarafınızda backend kimlik doğrulamasıyla veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve kimliği doğrulanmış kullanıcıları farklı şekilde yönetir. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik doğrulama hızlı başlangıç kılavuzunu](android-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywall'ınız için ürünleri almak üzere şunları yapmanız gerekir: 1. `getFlow` metoduna [placement](placements) ID'sini geçirerek `flow` nesnesini alın. 2. Bu flow için `getPaywallProducts` metodunu kullanarak ürünler dizisini alın. ```kotlin showLineNumbers fun loadPaywall() { Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value Adapty.getPaywallProducts(flow) { productResult -> when (productResult) { is AdaptyResult.Success -> { val products = productResult.value // Use products to build your custom paywall UI } is AdaptyResult.Error -> { val error = productResult.error // Handle the error } } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void loadPaywall() { Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); Adapty.getPaywallProducts(flow, productResult -> { if (productResult instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) productResult).getValue(); // Özel paywall UI'ınızı oluşturmak için ürünleri kullanın } else if (productResult instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) productResult).getError(); // Hatayı işleyin } }); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayı işleyin } }); } ``` ## Adım 2. Satın almaları kabul etme \{#step-2-accept-purchases\} Kullanıcı özel paywallınızda bir ürüne dokunduğunda, seçilen ürünle `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun purchaseProduct(activity: Activity, product: AdaptyPaywallProduct) { Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void purchaseProduct(Activity activity, AdaptyPaywallProduct product) { Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // Satın alma başarılı, profil güncellendi } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // Kullanıcı satın almayı iptal etti } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Satın alma beklemede (örn. kullanıcı nakit ile ödeyecek) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayı işle } }); } ``` ## 3. Adım: Satın almaları geri yükle \{#step-3-restore-purchases\} Google Play ve diğer uygulama mağazaları, abonelik sunan tüm uygulamaların kullanıcılara satın almalarını geri yükleyebilecekleri bir yol sunmasını zorunlu kılar. Kullanıcı geri yükle düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Restore successful, profile updated } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void restorePurchases() { Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // Geri yükleme başarılı, profil güncellendi } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayla ilgilen } }); } ``` ## Sonraki adımlar :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywallınız uygulamada gösterilmeye hazır. Paywalldan test satın alımı tamamlayabildiğinizden emin olmak için [Google Play Store'da satın alımlarınızı test edin](testing-on-android). Bunun gerçek bir uygulamada nasıl çalıştığını görmek için örnek uygulamamızdaki [ProductListFragment.kt](https://github.com/adaptyteam/AdaptySDK-Android/blob/master/app/src/main/java/com/adapty/example/ProductListFragment.kt) dosyasına göz atın; bu dosya, hata yönetimi, kullanıcı arayüzü geri bildirimi ve abonelik yönetimi dahil olmak üzere satın alma işlemlerinin nasıl ele alındığını göstermektedir. Ardından, paywall'u gösterip göstermeyeceğinizi ya da ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın alma işlemini tamamlayıp tamamlamadığını kontrol edin](android-check-subscription-status). --- # File: fetch-paywalls-and-products-android --- --- title: "Android SDK'da remote config paywalllar için paywall ve ürün çekme" description: "Kullanıcı monetizasyonunu artırmak için Adapty Android SDK'da paywall ve ürün çekme." --- Remote config ve özel paywallları göstermeden önce bunlara ilişkin bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. **Flow Builder** veya **Paywall Builder** ile özelleştirilmiş flow'ları veya paywallları çekme hakkında rehberlik için lütfen [Flow'ları ve paywallları getir](android-get-pb-paywalls) sayfasına bakın. :::tip 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](sample-apps) göz atın. :::
Mobil uygulamanızda flow'ları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow ya da paywall'ınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-android).
## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonudur. Bu platformlar arası ürünler, flow'lara ve paywall'lara entegre edilerek belirli mobil uygulama placement'larında sergilenebilir. Ürünleri göstermek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini hardcode etmeyin.** Hardcode etmeniz gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir flow bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // istenen flow } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. || **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir; ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli aralıklarla güncellendiğinden, oturum sırasında gereksiz ağ isteklerini önlemek amacıyla güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.

Adapty SDK, flow'ları ve paywall'ları iki katmanda depolar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywall'lar](android-use-fallback-paywalls). Ayrıca flow'ları ve paywall'ları daha hızlı getirmek için CDN, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanırız.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbellekteki veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

| Ürün ID'lerini kodunuza sabit olarak yazmayın! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme süresi gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Kodunuza sabit olarak yazmanız gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, `remoteConfigs` dizisi (yapılandırılmış her yerel ayar için bir giriş) ve `hasViewConfiguration` bayrağını içeren bir `AdaptyFlow` nesnesi. Flow için ürünleri almak üzere `getPaywallProducts(flow)` çağrısını kullanın. | :::note v4'te `locale` parametresi `getFlow`'dan `getFlowConfiguration`'a taşındı (yalnızca AdaptyUI ile render ederken kullanılır). Özel paywalllar için mevcut tüm locale'ler `flow.remoteConfigs` içinde birlikte döndürülür; kullanıcının cihaz diline veya uygulamanızın ayarına uygun locale'i seçin. ::: ## Ürünleri getir \{#fetch-products\} Flow'a sahip olduktan sonra, o flow'a karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(flow) { result -> when (result) { is AdaptyResult.Success -> { val products = result.value // the requested products } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallProducts(flow, result -> { if (result instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) result).getValue(); // istenen ürünler } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnelerinin listesi: ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler. | Kendi flow tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesindeki bu özelliklere erişmeniz muhtemelen gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı dokümana bakın. | Özellik | Açıklama | |----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin cihazın yerel ayarına değil, kullanıcının mağazada seçtiği ülkeye göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Fiyata sayı olarak erişmek için `product.price.amount` özelliğini kullanabilirsiniz; değer yerel para biriminde döner. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (hafta, ay, yıl vb.) göstermek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Buradan `unit` enum değerine ulaşarak dönem uzunluğunu alabilirsiniz (DAY, WEEK, MONTH, YEAR veya UNKNOWN). `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini rozet veya başka bir gösterge ile belirtmek için `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu kullanışlı özellikler yer alır:
• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerine sahip bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.
• `price`: İndirimli fiyatı sayı olarak verir. Ücretsiz denemeler için bu değer `0` olur.
• `localizedNumberOfPeriods`: Teklifin uzunluğunu cihazın yerel ayarına göre biçimlendirilmiş bir string olarak gösterir. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` şeklinde görünür.
• `subscriptionPeriod`: Teklif döneminin ayrıntılarına tek tek erişmek için bu özelliği kullanabilirsiniz. Abonelikler için açıklanan önceki bölümle aynı şekilde çalışır.
• `localizedSubscriptionPeriod`: İndirimin abonelik dönemini kullanıcının yerel ayarına göre biçimlendirilmiş olarak döndürür. | ## Varsayılan kitle flow'u ile flow getirmeyi hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız olduğunda ve kullanıcılarınızın internet bağlantısı zayıf olduğunda, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow'unu getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak kritik önem taşır: önerilen yaklaşım, yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-android#fetch-flow-information) bölümünde ayrıntılandırıldığı gibi `getFlow` metoduyla flow'u getirmektir. :::warning `getFlow` kullanımını neden öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecek) farklı flow'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamak ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşabileceğini kabul etmek zorunda kalırsınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize göre hedefleme dahil) kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı flow getirme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-android#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. || **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Bu seçeneği öneririz çünkü kullanıcılarınızın her zaman en güncel verilere erişmesini sağlar.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu durumda kullanıcılar en son verileri alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.

|
Remote config ve özel paywallları sergilemeye başlamadan önce, bunlarla ilgili bilgileri getirmeniz gerekiyor. Bu konunun remote config ve özel paywalllar ile ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları getirme konusunda rehberlik için lütfen [Paywall Builder paywalllarını ve yapılandırmalarını getirme](android-get-pb-paywalls) sayfasına bakın. :::tip 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](sample-apps) göz atın. :::
Mobil uygulamanızda paywallları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. [Bir paywall oluşturun ve ürünlerinizi paywall'unuza ekleyin](create-paywall) Adapty Kontrol Paneli'nde. 3. [Placement'lar oluşturun ve paywall'unuzu placement'a ekleyin](create-placement) Adapty Kontrol Paneli'nde. 4. [Adapty SDK'yı yükleyin](sdk-installation-android) mobil uygulamanıza.
## Paywall bilgilerini getirme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonunu temsil eder. Bu platformlar arası ürünler, belirli mobil uygulama placement'larında sergilenebilmesi için paywall'lara entegre edilir. Ürünleri gösterebilmek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan yazmanız gereken tek ID, placement ID'sidir. Paywall'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir paywall bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // istenen paywall } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // istenen paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi ise bölge içindir.

Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa önbellekten döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında temizlendiğini unutmayın.

Adapty SDK, paywall'ları iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](android-use-fallback-paywalls). Paywall'ların daha hızlı getirilmesi için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garanti edecek şekilde tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.

| Ürün ID'lerini hardcode etmeyin! Paywall'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zamanla değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Hardcode etmeniz gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün kimliklerinin listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | ## Ürünleri getir \{#fetch-products\} Paywall'a sahip olduktan sonra, buna karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall) { result -> when (result) { is AdaptyResult.Success -> { val products = result.value // the requested products } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallProducts(paywall, result -> { if (result instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) result).getValue(); // istenen ürünler } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnelerinin listesi; ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içerir. | Kendi paywall tasarımınızı uygularken, büyük ihtimalle [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın. | Özellik | Açıklama | |------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın dil ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın dil bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz; değer yerel para birimi cinsinden döner. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (hafta, ay, yıl vb.) göstermek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın dil ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Buradan `unit` enum'una erişerek süreyi (DAY, WEEK, MONTH, YEAR veya UNKNOWN) alabilirsiniz. `numberOfUnits` değeri ise dönem birimlerinin sayısını verir. Örneğin üç aylık bir abonelikte `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu yararlı özellikler yer alır:
• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerine sahip bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.
• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemelerde bu değer `0` olur.
• `localizedNumberOfPeriods`: Cihazın dil ayarına göre yerelleştirilmiş, teklifin süresini açıklayan bir metin. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak gösterilir.
• `subscriptionPeriod`: Teklif döneminin ayrıntılı bilgisini almak için bu özelliği kullanabilirsiniz; önceki bölümde abonelikler için açıklanan şekilde çalışır.
• `localizedSubscriptionPeriod`: Kullanıcının dil ayarına göre biçimlendirilmiş, indirim için abonelik dönemi metni. | ## Varsayılan kitle paywallı ile paywall getirmeyi hızlandırın \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywalliniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için paywall'ı çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Paywall Bilgisini Çekme](fetch-paywalls-and-products-android#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywall'ı çekmek olduğunu anlamanız kritik önem taşır. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekirse zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywall'larla sorun yaşamasını kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul edip daha hızlı paywall yükleme avantajından faydalanmak istiyorsanız, `getPaywallForDefaultAudience` yöntemini aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-android#fetch-paywall-information) açıklanan `getPaywall` yöntemini kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // istenen paywall } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience` metodu Android SDK 2.11.3 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirlediğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.

Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve kullanım önerilerimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar her zaman en güncel veriye ulaşamayabilir; ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için güvenle kullanılabilir.

Önbelleğin, uygulama yeniden başlatıldığında korunduğunu; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını unutmayın.

|
--- # File: present-remote-config-paywalls-android --- --- title: "Android SDK'da remote config ile tasarlanan paywallı render etme" description: "Adapty Android SDK'da remote config paywalllarını nasıl sunacağınızı keşfedin ve kullanıcı deneyimini kişiselleştirin." --- Remote config ile bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulama kodunuzda render işlemini kendiniz uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini siz belirlersiniz. Adapty, remote config'i çekmeniz için bir metot sağlar; özel paywallınızı nasıl göstereceğiniz tamamen size kalmıştır. ## Flow remote config'i alın ve sunun \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` dizisindeki yapılandırılmış her locale için bir `AdaptyRemoteConfig` girdisi taşır. Kullanıcının tercihiyle eşleşen locale'i seçin, ardından ihtiyacınız olan değerleri okuyun. ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value val config = flow.remoteConfigs.firstOrNull { it.locale == "en" } ?: flow.remoteConfigs.firstOrNull() val headerText = config?.dataMap?.get("header_text") as? String } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); AdaptyRemoteConfig config = null; for (AdaptyRemoteConfig remoteConfig : flow.getRemoteConfigs()) { if ("en".equals(remoteConfig.getLocale())) { config = remoteConfig; break; } } if (config == null && !flow.getRemoteConfigs().isEmpty()) { config = flow.getRemoteConfigs().get(0); } if (config != null && config.getDataMap().get("header_text") instanceof String) { String headerText = (String) config.getDataMap().get("header_text"); } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil ekranlarını ve yönlerini desteklediğinden emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunabilirsiniz. :::warning Adapty analitiğinin huni ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde [paywall görüntüleme etkinliğini kaydedin](present-remote-config-paywalls-android#track-paywall-view-events). ::: Paywallı görüntüledikten sonra satın alma akışını ayarlamaya devam edin. Kullanıcı bir satın alma işlemi yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](android-making-purchases) bölümünü okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](android-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellekte veri bulunmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme olaylarını izleyin \{#track-paywall-view-events\} Adapty, flow'larınızın ve paywall'larınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplasak da, görüntüleme olaylarını kaydetmek için sizin müdahaleniz gerekir; çünkü bir kullanıcının flow'u ne zaman gördüğünü yalnızca siz bilirsiniz. Bir görüntüleme olayı kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterlidir; bu olay, dönüşüm hunileri ve A/B testlerindeki metriklerinize yansıyacaktır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow veya paywallları görüntülüyorsanız `.logShowFlow(flow)` çağrısına gerek yoktur. Adapty bu durumlarda görüntülemeleri otomatik olarak takip eder. ::: ```kotlin showLineNumbers Adapty.logShowFlow(flow) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :-------- | :------- |:-----------------------------------------------------------------------------------------| | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla alınan bir `AdaptyFlow` nesnesi. | Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın koduna render işlemini eklemeniz gerekir. Remote config, ihtiyaçlarınıza göre şekillendirilmiş bir esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini tamamen siz belirlersiniz. Remote config aracılığıyla yapılandırdığınız özel paywall'ı göstermek için remote configuration'ı çeken bir metot sunuyoruz. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri oradan çekin. ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); AdaptyPaywall.RemoteConfig remoteConfig = paywall.getRemoteConfig(); if (remoteConfig != null) { if (remoteConfig.getDataMap().get("header_text") instanceof String) { String headerText = (String) remoteConfig.getDataMap().get("header_text"); } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Gerekli tüm değerleri aldıktan sonra, bunları görsel açıdan çekici bir sayfaya dönüştürme zamanı gelmiştir. Tasarımın farklı ekran boyutlarına ve yönlendirmelerine uyum sağladığından emin olun; böylece kullanıcılara her cihazda sorunsuz ve kullanışlı bir deneyim sunabilirsiniz. :::warning Aşağıda açıklandığı gibi [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-android#track-paywall-view-events) emin olun; bu sayede Adapty analitiği huni ve A/B testi veilerini doğru şekilde toplayabilir. ::: Paywallı gösterdikten sonra satın alma akışını kurarak devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](android-making-purchases) bölümünü inceleyin. [Yedek paywall olarak bir fallback paywall oluşturmanızı](android-use-fallback-paywalls) öneririz. Bu yedek paywall, internet bağlantısı olmadığında veya önbellekte veri bulunmadığında kullanıcıya gösterilir ve her koşulda kesintisiz bir deneyim sağlar. ## Paywall görüntüleme olaylarını kaydedin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın almaları otomatik olarak takip etsek de, paywall görüntülemelerini kaydetmek için sizin müdahaleniz gerekir; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu olay huni ve A/B testi metriklerinize yansıyacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywallları gösteriyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:---------------------------------------------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | --- # File: android-making-purchases --- --- title: "Android SDK'da mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın alma ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'ları yalnızca göstermek, satın almaları desteklemek için yeterlidir; bu yalnızca paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullandığınızda geçerlidir. Paywall Builder kullanmıyorsanız satın almayı tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime geçmesini ve istedikleri işlemleri gerçekleştirmesini sağlayan ana yoldur. Paywall'ınızda kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa, Adapty bunu satın alma sırasında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik olarak uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın. Diğer durumlarda [kullanıcının iOS'ta başlangıç teklifine uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlamak uygulamanızın yayın sırasında reddedilmesine yol açabilir. Ayrıca başlangıç teklifine hak kazanmış kullanıcıların tam fiyat üzerinden ücretlendirilmesine neden olabilir. ::: Tek bir adımı bile atlamadan [başlangıç yapılandırmasını](quickstart) tamamladığınızdan emin olun. Bu olmadan satın almaları doğrulayamayız. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir—bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlamıyla uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](android-implement-paywalls-manually) göz atın. ::: ```kotlin showLineNumbers Adapty.makePurchase(activity, product, null) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` ```java showLineNumbers Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // Grant access to the paid features } } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // Handle the case where the user canceled the purchase } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Handle deferred purchases (e.g., the user will pay offline with cash) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- | :----------------------------------------------------------------------------------------------- | | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.

Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için access level durumunu kontrol edin.

| :::warning **Not:** Apple'ın StoreKit sürümü v2.0'dan düşük ve Adapty SDK sürümü v2.9.0'dan düşükse, bunun yerine [Apple App Store paylaşımlı sırrı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem Apple tarafından artık kullanım dışı bırakılmıştır. ::: ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu işlemin nasıl çalışacağı uygulama mağazasına göre değişir. Google Play'de abonelik otomatik olarak güncellenmez. Geçişi aşağıda açıklandığı şekilde mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka bir abonelikle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```kotlin showLineNumbers Adapty.makePurchase( activity, product, AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build() ) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :--------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | zorunlu | Bir [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) nesnesi. | ```java showLineNumbers Adapty.makePurchase( activity, product, new AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build(), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // successful cross-grade } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // user canceled the purchase flow } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // the purchase has not been finished yet, e.g. user will pay offline by cash } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :--------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | zorunlu | Bir [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) nesnesi. | Abonelikler ve değiştirme modları hakkında daha fazla bilgiyi Google Geliştirici belgelerinde okuyabilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Değiştirme modları için Google önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değiştirme modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: Bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değiştirme modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik faturalama dönemi sona erdiğinde gerçekleşir. ### Ön ödemeli planları yönetme \{#manage-prepaid-plans\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin birkaç aylık yenilenmez abonelik satın alma), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build(); ``` --- # File: android-restore-purchase --- --- title: "Android SDK'da mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz kullanıcı deneyimi sağlamak için Adapty'de satın almaları nasıl geri yükleyeceğinizi öğrenin." --- Satın Almaları Geri Yükleme, kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden erişmesini sağlayan bir özelliktir. Bu özellik, uygulamayı silip yeniden yükleyen ya da yeni bir cihaza geçip daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça faydalıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywallerde, satın almalar sizin tarafınızdan ek bir kod yazılmasına gerek kalmadan otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz. ::: Paywalli özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almayı geri yüklemek için `.restorePurchases()` metodunu çağırın: ```kotlin showLineNumbers Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); if (profile != null) { AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // successful access restore } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------| | **Profile** |

Bir [`AdaptyProfile`](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi. Bu model, access level, abonelik ve abonelik dışı satın alma bilgilerini içerir.

Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level durumunu** kontrol edin.

| :::tip 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](sample-apps) göz atın. ::: --- # File: implement-observer-mode-android --- --- title: "Android SDK'da Observer modunu uygulama" description: "Android SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve Adapty'ye tam geçişe hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer Modu, gelişmiş analitik ve attribution ile analitik sistemleriyle sorunsuz entegrasyon sunar. Bu sizin için yeterliyse yapmanız gerekenler: 1. `observerMode` parametresini `true` olarak ayarlayarak Adapty SDK'yı yapılandırırken Observer modunu açın. [Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk) için kurulum talimatlarını takip edin. 2. Mevcut satın alma altyapınızdan Adapty'ye [işlemleri bildirin](report-transactions-observer-mode-android). ## Observer modu kurulumu \{#observer-mode-setup\} Satın almaları ve abonelik durumunu kendiniz yönetiyorsanız ve abonelik olayları ile analitik göndermek için Adapty kullanıyorsanız Observer modunu açın. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle bunu kendiniz yönettiğinizden emin olun. ::: ```kotlin showLineNumbers class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ) } ``` ```java showLineNumbers public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ); } ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden boolean değer. Varsayılan değer `false`'tur. | ## Observer Modunda Adapty paywalllarını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywalllarını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer modunda biraz ek kurulum gerektirir. Yukarıdaki adımlara ek olarak yapmanız gerekenler: 1. [Remote config paywallları](present-remote-config-paywalls-android) için paywallları her zamanki gibi görüntüleyin. Paywall Builder paywallları için [Android](android-present-paywall-builder-paywalls-in-observer-mode)'a özel kurulum kılavuzlarını takip edin. 3. Satın alma işlemleriyle [paywallları ilişkilendirin](report-transactions-observer-mode-android). --- # File: report-transactions-observer-mode-android --- --- title: "Android SDK'da Observer Mode'da işlemleri raporlama" description: "Android SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini raporlayın." --- Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan gelen işlemleri kendiniz raporlamanız gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız çok önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanın. :::warning **İşlem raporlamayı atlamayın!** `reportTransaction` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywallları kullanıyorsanız, işlemi raporlarken `variationId` bilgisini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```kotlin showLineNumbers val transactionInfo = TransactionInfo.fromPurchase(purchase) Adapty.reportTransaction(transactionInfo, variationId) { result -> if (result is AdaptyResult.Success) { // success } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | ---------------------------------------------------------- | | transactionInfo | zorunlu | Satın almadan elde edilen TransactionInfo; buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java showLineNumbers TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); Adapty.reportTransaction(transactionInfo, variationId, result -> { if (result instanceof AdaptyResult.Success) { // success } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | ---------------------------------------------------------- | | transactionInfo | zorunlu | Satın almadan elde edilen TransactionInfo; buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan gelen işlemleri raporlamanız ya da geri yüklemeniz gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız çok önemlidir. İşlemi Adapty'ye raporlamak için `restorePurchases` kullanın. :::warning **Satın alma geri yüklemeyi atlamayın!** `restorePurchases` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywallları kullanıyorsanız, `setVariationId` metoduyla işleminizi satın almaya yol açan paywall ile ilişkilendirin. Bu, satın almanın tetikleyen paywall'a doğru şekilde atfedilmesini ve analizlerin doğru olmasını sağlar. Bu adım yalnızca Adapty paywalllarını kullanıyorsanız gereklidir. ```kotlin showLineNumbers Adapty.restorePurchases { result -> if (result is AdaptyResult.Success) { // success } } Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (`purchase.getOrderId`); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { // success } }); Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (`purchase.getOrderId`); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | **İşlemleri raporlama** Observer Mode'da Adapty'ye işlem raporlamak için `restorePurchases` kullanın. Ayrıntılar için [Mobil Kodda Satın Alma Geri Yükleme](android-restore-purchase) sayfasına bakın. :::warning **İşlem raporlamayı atlamayın!** `restorePurchases` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: **Paywallları işlemlerle ilişkilendirme** Adapty SDK, satın almaları siz yönettiğiniz için satın alma kaynağını belirleyemez. Bu nedenle Observer mode'da paywallları ve/veya A/B testlerini kullanmayı planlıyorsanız, app store'dan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Uygulamanızı yayınlamadan önce bunu doğru şekilde yapılandırmanız önemlidir; aksi hâlde analizlerde hatalara yol açar. ```kotlin Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (purchase.getOrderId); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` | Parametre | Zorunluluk | Açıklama | | ------------------------------------------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (purchase.getOrderId); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | --- # File: android-present-paywall-builder-paywalls-in-observer-mode --- --- title: "Android SDK'da Observer mode'da Paywall Builder paywalllarını sunma" description: "Adapty'nin Paywall Builder'ını kullanarak observer mode'da paywallları nasıl sunacağınızı öğrenin." --- Flow Builder veya Paywall Builder kullanarak bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etmeniz konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. :::warning Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız bunun yerine [Android - Flow ve paywall'ları gösterme](android-present-paywalls) konusuna bakın. :::
Flow'ları göstermeye başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play ile](initial-android) başlangıç entegrasyonunu yapın. 2. Adapty SDK'yı yükleyip yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza [Android için](sdk-installation-android) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'lar veya paywall'lar yapılandırın](create-paywall) ve ürünleri bunlara atayın. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow'larınızı ya da paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını alın](android-get-pb-paywalls).

1. `AdaptyUiObserverModeHandler`'ı uygulayın. `onPurchaseInitiated` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu callback'e yanıt olarak özel satın alma flow'unuzu tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, flow, flowView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, flow, flowView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Observer mode'da geri yüklemeleri yönetmek için `getRestoreHandler()` metodunu geçersiz kılın. Varsayılan olarak `null` döndürür; bu durumda Adapty'nin yerleşik `Adapty.restorePurchases()` flow'u kullanılır. Kendi geri yükleme implementasyonunuzu sağlamak için: ```kotlin showLineNumbers val observerModeHandler = object : AdaptyUiObserverModeHandler { // onPurchaseInitiated implementation (see above) override fun getRestoreHandler() = AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore -> onStartRestore() yourBillingClient.restorePurchases( onSuccess = { restoredPurchases -> onFinishRestore() //handle successful restore }, onError = { onFinishRestore() //handle error } ) } } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() { // onPurchaseInitiated implementation (see above) @Override public RestoreHandler getRestoreHandler() { return (onStartRestore, onFinishRestore) -> { onStartRestore.invoke(); yourBillingClient.restorePurchases( restoredPurchases -> { onFinishRestore.invoke(); //handle successful restore }, error -> { onFinishRestore.invoke(); //handle error } ); }; } }; ``` AdaptyUI'yı satın alma veya geri yükleme işlemi hakkında bilgilendirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi doğru flow davranışı için gereklidir: | Callback | Açıklama | | :----------------- |:--------------------------------------------------------------------------------------------------| | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için çağrılması gereken callback. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için çağrılması gereken callback. | | onStartRestore() | İsteğe bağlı. Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için çağrılabilecek callback. | | onFinishRestore() | İsteğe bağlı. Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için çağrılabilecek callback. | 2. Flow'u cihaz ekranında görüntülemek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın veya `AdaptyFlowView`'i doğrudan oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //add to the view hierarchy if needed, or you receive it from xml ... flowView.showFlow(flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, onu view hiyerarşisine ekleyebilir ve görüntüleyebilirsiniz. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyFlowScreen( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **flowConfiguration** | zorunlu | Flow'un görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi sağlayın. Yüklemek için `AdaptyUI.getFlowConfiguration(flow)` metodunu kullanın. Daha fazla bilgi için [Görünüm yapılandırmasını getir](android-get-pb-paywalls#fetch-the-view-configuration) konusuna bakın. | | **products** | isteğe bağlı | Ürünlerin ekranda gösterilme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Flow olaylarını izlemek için bir `AdaptyFlowEventListener` sağlayın. Kullanım kolaylığı açısından `AdaptyFlowDefaultEventListener` sınıfını genişletmeniz önerilir. Daha fazla bilgi için [Flow ve paywall olaylarını yönet](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı | Insets, tıklanabilir öğelerin sistem çubuklarının arkasına gizlenmesini önlemek için flow'un etrafındaki boşluklardır. Varsayılan: `Unspecified`; bu değer Adapty'nin insets'leri otomatik olarak ayarlamasına izin verir. Bkz. [Flow insets'lerini değiştir](android-present-paywalls#change-flow-insets). | | **customAssets** | isteğe bağlı | Çalışma zamanında flow veya paywall'unuzdaki görsel ve videoları değiştirmek için bir `AdaptyCustomAssets` nesnesi geçirin. Daha fazla bilgi için [Varlıkları özelleştir](android-get-pb-paywalls#customize-assets) konusuna bakın. | | **tagResolver** | isteğe bağlı | Flow metni içindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve onu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **observerModeHandler** | Observer mode için zorunlu | Bir önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | :::warning Satın alma işlemlerini [paywall'larla ilişkilendirmeyi](report-transactions-observer-mode-android) unutmayın. Aksi takdirde, Adapty satın almanın kaynak flow'unu belirleyemez. :::
Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu kurun. 2. Adapty SDK'yı yükleyip yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza [Android için](sdk-installation-android) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri onlara atayın](create-paywall) ve Paywall Builder ile özelleştirin. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını getirin](android-get-pb-paywalls).

1. `AdaptyUiObserverModeHandler`'ı uygulayın. `onPurchaseInitiated` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu callback'e yanıt olarak özel satın alma flow'unuzu tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Observer mode'da restore işlemlerini yönetmek için `getRestoreHandler()` metodunu override edin. Varsayılan olarak `null` döndürür; bu durumda Adapty'nin yerleşik `Adapty.restorePurchases()` flow'u kullanılır. Kendi restore implementasyonunuzu sağlamak için: ```kotlin showLineNumbers val observerModeHandler = object : AdaptyUiObserverModeHandler { // onPurchaseInitiated implementation (see above) override fun getRestoreHandler() = AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore -> onStartRestore() yourBillingClient.restorePurchases( onSuccess = { restoredPurchases -> onFinishRestore() //handle successful restore }, onError = { onFinishRestore() //handle error } ) } } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() { // onPurchaseInitiated implementation (see above) @Override public RestoreHandler getRestoreHandler() { return (onStartRestore, onFinishRestore) -> { onStartRestore.invoke(); yourBillingClient.restorePurchases( restoredPurchases -> { onFinishRestore.invoke(); //handle successful restore }, error -> { onFinishRestore.invoke(); //handle error } ); }; } }; ``` Ödeme veya geri yükleme sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi paywall'un düzgün çalışması için gereklidir: | Callback | Açıklama | | :----------------- |:-------------------------------------------------------------------------------------------------------| | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | İsteğe bağlı. Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılabilir. | | onFinishRestore() | İsteğe bağlı. Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılabilir. | 2. Görsel paywallı cihaz ekranında görüntülemek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getPaywallView()` metodunu çağırın ya da doğrudan `AdaptyPaywallView` oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.showPaywall(viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, onu view hiyerarşisine ekleyebilir ve görüntüleyebilirsiniz. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **Products** | isteğe bağlı | Ekranda ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **ViewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyViewConfiguration` nesnesi sağlayın. Yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywallın görsel yapılandırmasını getirme](#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **EventListener** | isteğe bağlı | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı için `AdaptyUiDefaultEventListener`'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını işleme](android-handling-events) konusuna bakın. | | **PersonalizedOfferResolver** | isteğe bağlı | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver`'ı uygulayın ve `AdaptyPaywallProduct`'ı ürünün fiyatı kişiselleştirilmişse `true`, aksi hâlde `false` ile eşleştiren kendi mantığınızı geçirin. | | **TagResolver** | isteğe bağlı | Paywall metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve bunu karşılık gelen bir dizeyle eşleştirir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **ObserverModeHandler** | Observer mode için zorunlu | Önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | | **variationId** | zorunlu | Varyasyonun dize tanımlayıcısı. Bunu [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | | **transaction** | zorunlu |

iOS, StoreKit 1 için: bir [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.

iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.

Android için: Satın almanın billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneği olduğu satın almanın String tanımlayıcısı (`purchase.getOrderId()`).

|
Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu yapılandırın. 2. Adapty SDK'yı yükleyin ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza başvurun: [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) ve [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk). 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri bunlara atayın](create-paywall) ve Paywall Builder kullanarak özelleştirin. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını getirin](android-get-pb-paywalls).
1. `AdaptyUiObserverModeHandler` arayüzünü uygulayın. `AdaptyUiObserverModeHandler`'ın geri çağırımı (`onPurchaseInitiated`), kullanıcı bir satın alma işlemi başlattığında sizi bilgilendirir. Bu geri çağırıma yanıt olarak özel satın alma akışınızı şu şekilde tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Ayrıca, bu callback'leri AdaptyUI'ya iletmeyi unutmayın. Bu, yükleyiciyi göstermek gibi paywall'ın doğru çalışması için gereklidir: | Kotlin'de Callback | Java'da Callback | Açıklama | | :----------------- | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------- | | onStartPurchase() | onStartPurchase.invoke() | Bu callback, satın alma işleminin başladığını AdaptyUI'ya bildirmek için çağrılmalıdır. | | onFinishPurchase() | onFinishPurchase.invoke() | Bu callback, satın alma işleminin başarıyla tamamlandığını, tamamlanamadığını veya iptal edildiğini AdaptyUI'ya bildirmek için çağrılmalıdır. | 2. Görsel paywall'ı görüntüleyebilmek için önce başlatmanız gerekir. Bunun için `AdaptyUI.getPaywallView()` metodunu çağırın ya da `AdaptyPaywallView`'i doğrudan oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler, ) //======= OR ======= val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { setEventListener(eventListener) setObserverModeHandler(observerModeHandler) showPaywall( viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver, tagResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler ); //======= OR ======= AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver); ``` ```xml showLineNumbers ``` Görünüm başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyip gösterebilirsiniz. İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Products** | opsiyonel | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **ViewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyViewConfiguration` nesnesi sağlayın. Yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywall'ın görsel yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **Insets** | zorunlu | İçerik için dikey kenar boşlukları oluşturmak amacıyla sistem çubuklarının kapladığı alan hakkında bilgi içeren bir `AdaptyPaywallInsets` nesnesi tanımlayın. Ne durum çubuğu ne de gezinme çubuğu `AdaptyPaywallView`'ı kapatmıyorsa `AdaptyPaywallInsets.NONE` geçin. Sistem çubuklarının UI'ınızın bir kısmını kapladığı tam ekran modunda, insets'leri tablonun altında gösterildiği şekilde alın. | | **EventListener** | opsiyonel | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı açısından AdaptyUiDefaultEventListener'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **PersonalizedOfferResolver** | opsiyonel | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver`'ı uygulayın ve `AdaptyPaywallProduct`'ı ürünün fiyatı kişiselleştirilmişse true, değilse false olarak eşleyen kendi mantığınızı geçirin. | | **TagResolver** | opsiyonel | Paywall metni içindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve onu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **ObserverModeHandler** | Observer modu için zorunlu | Önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | | **variationId** | zorunlu | Varyasyonun dize tanımlayıcısı. [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliğini kullanarak elde edebilirsiniz. | | **transaction** | zorunlu |

iOS, StoreKit1 için: bir [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.

iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.

Android için: Satın almanın billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneği olduğu satın almanın dize tanımlayıcısı (`purchase.getOrderId()`).

| Tam ekran modunda sistem çubuklarının kullanıcı arayüzünüzün bir bölümünü kapladığı durumlarda, inset'leri şu şekilde elde edin: ```kotlin showLineNumbers import androidx.core.graphics.Insets import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.of(insets.top, insets.bottom) paywallView.setEventListener(eventListener) paywallView.setObserverModeHandler(observerModeHandler) paywallView.showPaywall(viewConfig, products, paywallInsets, personalizedOfferResolver, tagResolver) } ``` ```java showLineNumbers import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, systemBarInsets.bottom); paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, paywallInsets, personalizedOfferResolver, tagResolver); return insets; }); ``` Returns: | Object | Description | | :------------------ | :------------------------------------------------- | | `AdaptyPaywallView` | İstenen paywall ekranını temsil eden nesne. | :::warning [Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode-android) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywall'dan geldiğini belirleyemez. :::
--- # File: android-troubleshoot-purchases --- --- title: "Android SDK'da satın alma sorunlarını giderme" description: "Android SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, Android SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrılıyor ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor, ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu durum genellikle Google Play Store kurulumunun eksik olduğuna ya da yapılandırma sorunlarına işaret eder. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## makePurchase iki kez çağrılıyor \{#makepurchase-is-invoked-twice\} **Sorun**: `makePurchase` metodu aynı satın alma için birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya hızlı kullanıcı etkileşimleri nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyelrorcantmakepayments-in-observer-mode\} **Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmanız ya da observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode-android) sayfasına bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan faturalandırma kullanılamıyor hatası alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın kullanılamadığını belirten bir Google Play Faturalandırma Kitaplığı hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store belgelerinden daha fazla bilgi edinebilirsiniz: [BillingResult yanıt kodlarını yönetme](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamıyor \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor ile ilgili sorunlarla karşılaşıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu işlem çoğu zaman sandbox ile ilgili satın alma tamamlama handler sorunlarını çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekirse [geçiş kılavuzlarını](android-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Yeni SDK sürümlerinde pek çok sorun giderilmiştir. --- # File: android-identifying-users --- --- title: "Android SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini geliştirmek için Adapty'de kullanıcıları tanımlayın (Android)." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamanız gerekir. Kullanıcıları Customer User ID'lerine göre [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz. ### Yapılandırma sırasında Customer User ID ayarlama \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçin: ```kotlin showLineNumbers Adapty.activate(applicationContext, "PUBLIC_SDK_KEY", customerUserId = "YOUR_USER_ID") ``` :::tip 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](sample-apps) göz atın. ::: ### Yapılandırma sonrasında Customer User ID ayarlama \{#setting-customer-user-id-after-configuration\} SDK yapılandırmasında kullanıcı ID'niz yoksa, daha sonra istediğiniz zaman `.identify()` metoduyla ayarlayabilirsiniz. Bu metodun en yaygın kullanım senaryoları; kayıt veya oturum açma sonrasında, kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçtiği anlardır. ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> if (error == null) { // successful identify } } ``` ```java showLineNumbers Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` İstek parametreleri: - **Customer User ID** (zorunlu): string türünde kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Bir kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahiptir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmaya otomatik olarak geçecektir. Anonim kullanıcıya özel özellikler veya üçüncü taraf ağlardan attribution gibi herhangi bir veri iletildiyse, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden istemeniz gerektiğini unutmayın. ::: ### Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\} İstediğiniz zaman `.logout()` metodunu çağırarak kullanıcının oturumunu kapatabilirsiniz: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` Ardından `.identify()` metodunu kullanarak kullanıcı girişi yapabilirsiniz. ### Cihazlar Arası Kullanıcı Tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: android-setting-user-attributes --- --- title: "Android SDK'da kullanıcı özelliklerini ayarlama" description: "Daha iyi kitle segmentasyonu için Adapty'de kullanıcı özelliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulama kullanıcılarınıza e-posta, telefon numarası gibi isteğe bağlı özellikler ekleyebilirsiniz. Bu özellikleri kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz. ### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } ``` ```java showLineNumbers AdaptyProfileParameters.Builder builder = new AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(new AdaptyProfile.Date(1970, 1, 3)); Adapty.updateProfile(builder.build(), error -> { if (error != null) { // handle the error } }); ``` `updateProfile` metoduyla daha önce ayarladığınız özellikler sıfırlanmaz. :::tip 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](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen `` anahtarları ve `` değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| |

email

phoneNumber

firstName

lastName

| String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı özellikleri \{#custom-user-attributes\} Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin fitness uygulamaları için haftalık egzersiz sayısı, dil öğrenme uygulamaları için kullanıcının bilgi düzeyi gibi. Bu özellikleri, hedefli paywall'lar ve teklifler oluşturmak için segmentlerde kullanabilir; ayrıca hangi ürün metriklerinin geliri en çok etkilediğini anlamak için analitikte de değerlendirebilirsiniz. ```kotlin showLineNumbers builder.withCustomAttribute("key1", "value1") ``` ```java showLineNumbers builder.withCustomAttribute("key1", "value1"); ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```kotlin showLineNumbers builder.withRemovedCustomAttribute("key2") ``` ```java showLineNumbers builder.withRemovedCustomAttribute("key2"); ``` Bazen önceden hangi özel özelliklerin ayarlandığını öğremeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı özellikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, son senkronizasyondan bu yana sunucudaki özellikler değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel özellik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ile şu karakterleri içerebilir: `_` `-` `.` - Değer, en fazla 50 karakter uzunluğunda string veya float olabilir. --- # File: android-listen-subscription-changes --- --- title: "Android SDK'da abonelik durumunu kontrol etme" description: "Android uygulamanızda müşteri elde tutmayı iyileştirmek için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek çok kolaydır. Ürün kimliklerini kodunuza manuel olarak eklemenize gerek yoktur. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. Abonelik durumunu kontrol etmeye başlamadan önce [Gerçek Zamanlı Geliştirici Bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) kurulumunu yapın. ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesinin özellikleridir. Profili uygulamanız başladığında, örneğin [bir kullanıcı tanımladığınızda](android-identifying-users#setting-customer-user-id-on-configuration) alıp değişiklikler gerçekleştiğinde güncellemenizi öneririz. Bu sayede profil nesnesini tekrar tekrar istek göndermeden kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Profil güncellemelerini dinleme, access level dahil](android-listen-subscription-changes) bölümünde açıklandığı gibi profil değişikliklerini dinleyin. :::tip 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](sample-apps) göz atın. ::: ## Sunucudan access level alma \{#retrieving-the-access-level-from-the-server\} Sunucudan access level almak için `.getProfile()` metodunu kullanın: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- | ------------------------------------------------------------ | | Profile |

Bir [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi. Genel olarak, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.

`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu sağlar. Herhangi bir nedenle (örneğin internet bağlantısı olmadığında) Adapty SDK sunucudan bilgi alamazsa, önbellekteki veriler döndürülür. Adapty SDK'nın bilgileri mümkün olduğunca güncel tutmak için `AdaptyProfile` önbelleğini düzenli olarak güncellediğini de belirtmek gerekir.

| `.getProfile()` metodu, kullanıcı profilini size sağlar ve bu profilden access level durumunu öğrenebilirsiniz. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız "sports" ve "science" gibi access level'lar oluşturabilirsiniz. Ancak çoğu durumda yalnızca bir access level'a ihtiyaç duyarsınız; bu durumda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmeye yönelik bir örnek: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("premium"); if (premium != null && premium.isActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` ```java showLineNumbers t Adapty.setOnProfileUpdatedListener(profile -> { // handle any changes to subscription state }); ``` Adapty, uygulamanın başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'da uygulanan önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu kullanılamaz olsa bile, profil abonelik durumuna ilişkin bilgilere önbellekteki verilerden erişilebilir. Ancak önbellekten doğrudan veri talep etmenin mümkün olmadığını belirtmek gerekir. SDK, profille ilgili güncellemeleri ve değişiklikleri kontrol etmek için sunucuyu periyodik olarak her dakika sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler olduğunda, bunlar önbellekteki veriyle sunucuyla senkronize kalması için önbelleğe gönderilir. --- # File: kids-mode-android --- --- title: "Android SDK'da Kids Mode" description: "Google politikalarına uymak için Kids Mode'u kolayca etkinleştirin. Android SDK'da GAID veya reklam verisi toplanmaz." --- Android uygulamanız çocuklara yönelikse [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikalara uygun şekilde yapılandırabilir ve uygulama mağazası incelemelerini geçebilirsiniz. ## Ne yapılması gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunlara ek olarak, customer user ID kullanımında dikkatli olmanızı öneririz. `` formatındaki kullanıcı kimlikleri, e-posta kullanımında olduğu gibi kişisel veri toplama olarak değerlendirilecektir. Kids Mode için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (ör. karma kimlikler veya cihaz tarafından üretilen UUID'ler) kullanmaktır. ## Kids Mode'u Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'ndeki güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzdaki güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için Adapty SDK'yı başlatırken Android Advertising ID (AAID/GAID) ve IP adresi toplamasını devre dışı bırakmanız gerekir: **Kotlin:** ```kotlin showLineNumbers override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ) } ``` **Java:** ```java showLineNumbers @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ); } ``` ### Android manifest'inizdeki güncellemeler \{#updates-in-your-android-manifest\} :::note Uygulamanız **yalnızca** çocuklara yönelikse ve Android 13 (API 33) veya daha yüksek bir sürümü hedefliyorsa, Google Play `AD_ID` iznini talep etmemenizi zorunlu kılar. Uygulamanızdaki başka bir SDK (analitik, attribution veya reklam), manifest birleştirme yoluyla bu izni ekleyebilir. `withAdIdCollectionDisabled(true)` ayarını yapmak, Adapty'nin kimliği toplamasını engeller; ancak başka bir SDK tarafından tanımlanan bir izni kaldırmaz. ::: İzni kaldırmak için aşağıdaki kodu `app/src/main/AndroidManifest.xml` dosyasındaki `` öğesinin içine ekleyin. `` öğesinin `xmlns:tools="http://schemas.android.com/tools"` bildirimini içermesi gerekir. ```xml showLineNumbers title="AndroidManifest.xml" ``` --- # File: android-get-onboardings --- --- title: "Android SDK'da onboarding'leri al" description: "Adapty'de Android için onboarding'leri nasıl alacağınızı öğrenin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları edinme](android-get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](android-present-paywalls) sayfalarına bakın. ::: Adapty Kontrol Paneli'nde builder ile [onboarding'in görsel kısmını tasarladıktan](design-onboarding) sonra, onu Android uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, onboarding'i placement ile ilişkilendirmek ve aşağıda açıklanan görünüm yapılandırmasını almaktır. Başlamadan önce şunları sağlayın: 1. [Adapty Android SDK](sdk-installation-android) sürüm 3.8.0 veya daha yüksek sürümü yüklemiş olun. 2. [Bir onboarding oluşturmuş](create-onboarding) olun. 3. Onboarding'i bir [placement](placements)'a eklemiş olun. ## Onboarding'i çekme \{#fetch-onboarding\} Kodsuz builder'ımızla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın çekip göstermesi gereken bir yapılandırma içeren container olarak saklanır. Bu container tüm deneyimi yönetir — hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (quiz yanıtları veya form girişleri gibi) nasıl işleneceğini belirler. Container ayrıca analitik olaylarını otomatik olarak takip eder, dolayısıyla ayrıca görüntüleme takibi eklemeniz gerekmez. En iyi performans için, kullanıcılara göstermeden önce görsellerin yüklenmesine yeterli zaman tanımak amacıyla onboarding yapılandırmasını erken aşamada çekin. Onboarding almak için `getOnboarding` metodunu kullanın: ```kotlin showLineNumbers Adapty.getOnboarding("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // the requested onboarding } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa bunu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ama internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı çekmek için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı sağlamak için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.

Nadiren bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`, burada `.seconds` `import com.adapty.utils.seconds`'dan gelir) ya da `TimeInterval.seconds(5)` kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyOnboarding`](https://android.adapty.io/adapty/com.adapty.models/-adapty-onboarding/) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding çekmeyi hızlandırma \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Onboarding'ler genellikle neredeyse anında çekilir, dolayısıyla bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz olduğunda ve kullanıcılarınızın internet bağlantısı zayıf olduğunda, onboarding'i çekmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için onboarding'i çeken `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Çekme](#fetch-onboarding) bölümünde açıklandığı gibi `getOnboarding` metodu ile onboarding çekmek olduğunu unutmamak önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı değerlendirin; çünkü ikincisinin önemli kısıtlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorun yaratabilir; geriye dönük uyumlu tasarımlar yapmanızı ya da eski sürümlerin yanlış görüntüleneceğini kabul etmenizi gerektirebilir. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı çekme bu dezavantajlardan ağır basıyorsa aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```kotlin Adapty.getOnboardingForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // Handle successful onboarding retrieval } is AdaptyResult.Error -> { val error = result.error // Handle error case } } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa bunu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ama internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı çekmek için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı sağlamak için tasarlanmıştır.

| --- # File: android-present-onboardings --- --- title: "Android SDK'da onboarding'leri göster" description: "Etkili kullanıcı etkileşimi için Android'de onboarding'leri nasıl sunacağınızı öğrenin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı olmadan kullanım elde edersiniz. Başlamak için [Flow'ları ve paywall'ları al](android-get-pb-paywalls) ve [Flow'ları ve paywall'ları göster](android-present-paywalls) sayfalarına göz atın. ::: Başlamadan önce şunlardan emin olun: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 veya daha yeni bir sürümünü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Onboarding Builder ile bir onboarding özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render işlemiyle uğraşmanıza gerek yok. Bu tür bir onboarding, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. Cihaz ekranında görsel onboarding'i gösterebilmek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getOnboardingView()` metodunu çağırın veya `OnboardingView`'ı doğrudan oluşturun: ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener); ``` ```xml ``` View başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyebilir ve cihaz ekranında görüntüleyebilirsiniz. İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :-------- | :------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfig** | zorunlu | `AdaptyUI.getOnboardingConfiguration()` ile elde edilen onboarding yapılandırması | | **eventListener** | zorunlu | Onboarding olaylarını işlemek için `AdaptyOnboardingEventListener` uygulaması. Ayrıntılar için [Onboarding olaylarını işleme](android-handle-onboarding-events) bölümüne bakın. | ## Yükleme göstergesi rengini değiştirme \{#change-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini şu şekilde geçersiz kılabilirsiniz: ```xml ``` ## Splash ekranı ile onboarding arasına sorunsuz geçiş ekleme \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\} Varsayılan olarak, splash ekranı ile onboarding arasında onboarding tam olarak yüklenene kadar yükleme ekranı görünür. Ancak geçişi daha akıcı hale getirmek istiyorsanız bunu özelleştirebilir; splash ekranını uzatabilir ya da başka bir şey gösterebilirsiniz. Bunu yapmak için `res/layout` dizininde `adapty_onboarding_placeholder_view.xml` dosyası oluşturun ve onboarding yüklenirken gösterilecek yer tutucuyu orada tanımlayın. Bir yer tutucu tanımladığınızda onboarding arka planda yüklenir ve hazır olduğunda otomatik olarak görüntülenir. ## Güvenli alan dolgularını devre dışı bırakma \{#disable-safe-area-paddings\} Varsayılan olarak, onboarding view durum çubuğu ve gezinme çubuğu gibi sistem arayüzü öğelerini önlemek amacıyla güvenli alan dolgularını otomatik olarak uygular. Ancak bu davranışı devre dışı bırakarak layout üzerinde tam kontrol sahibi olmak istiyorsanız `safeAreaPaddings` parametresini `false` olarak ayarlayabilirsiniz. ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener, safeAreaPaddings = false ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener, safeAreaPaddings = false ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener, false ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener, false); ``` Alternatif olarak, uygulamanıza bir boolean kaynağı ekleyerek bu davranışı genel düzeyde kontrol edebilirsiniz: ```xml false ``` `safeAreaPaddings` değeri `false` olarak ayarlandığında, onboarding otomatik dolgu ayarlaması yapılmadan tam ekrana uzanır; bu sayede layout üzerinde tam kontrol sağlanır ve onboarding içeriği ekranın tamamını kullanabilir. ## Onboardinglerde linklerin nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboardinglerde linklerin nasıl açılacağını özelleştirme, Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboardinglerdeki linkler uygulama içi bir tarayıcıda açılır. Bu, web sayfalarını uygulamanızın içinde göstererek kullanıcıların uygulamalar arasında geçiş yapmadan görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sunar. Linklerin bunun yerine harici bir tarayıcıda açılmasını tercih ederseniz, `externalUrlsPresentation` parametresini `AdaptyWebPresentation.ExternalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```kotlin val onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ) ``` ```java AdaptyOnboardingConfiguration onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding, AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ); ``` --- # File: android-handle-onboarding-events --- --- title: "Android SDK'da onboarding olaylarını yönetme" description: "Adapty kullanarak Android'de onboarding ile ilgili olayları yönetin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda native olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü ve hissi, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywallları al](android-get-pb-paywalls) ve [Flow'ları ve paywallları göster](android-present-paywalls) bölümlerine bakın. ::: Başlamadan önce şunları sağlayın: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 veya daha yeni bir sürümünü yüklediniz. 2. Bir [onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin. Android uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyOnboardingEventListener` arayüzünü uygulayın. ## Özel eylemler \{#custom-actions\} Builder'da bir düğmeye **custom** (özel) eylem ekleyebilir ve buna bir ID atayabilirsiniz. Ardından bu ID'yi kodunuzda kullanarak özel eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir düğmeye dokunduğunda, `onCustomAction` delegate metodu builder'daki eylem ID'siyle tetiklenir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```kotlin showLineNumbers class YourActivity : AppCompatActivity() { private val eventListener = object : AdaptyOnboardingEventListener { override fun onCustomAction(action: AdaptyOnboardingCustomAction, context: Context) { when (action.actionId) { "allowNotifications" -> { // Request notification permissions } } } override fun onError(error: AdaptyOnboardingError, context: Context) { // Handle errors } // ... other required delegate methods } } ```
Olay örneği (Genişletmek için tıklayın) ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
## Onboarding'i kapatma \{#closing-onboarding\} Kullanıcı **Close** eylemi atanmış bir düğmeye dokunduğunda onboarding kapatılmış sayılır. Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerekir. Örneğin: :::important Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerekir. Örneğin onboarding'in kendisini ekrandan kaldırmanız gerekir. ::: Örneğin: ```kotlin override fun onCloseAction(action: AdaptyOnboardingCloseAction, context: Context) { // Dismiss the onboarding screen (context as? Activity)?.onBackPressed() } ```
Olay örneği (Genişletmek için tıklayın) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
## Paywall açma \{#opening-a-paywall\} :::tip Eğer paywall'ı onboarding içinde açmak istiyorsanız bu olayı ele alın. Paywall kapandıktan sonra açmak istiyorsanız daha doğrudan bir yöntem var: [`AdaptyOnboardingCloseAction`](#closing-onboarding) olayını ele alın ve olay verisine gerek kalmadan paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, action ID'yi bir paywall placement ID'siyle eşit tutmaktır. Bu şekilde `AdaptyOnboardingOpenPaywallAction` sonrasında placement ID'yi kullanarak paywall'ı hemen alıp açabilirsiniz: ```kotlin override fun onOpenPaywallAction(action: AdaptyOnboardingOpenPaywallAction, context: Context) { // Get the paywall using the placement ID from the action Adapty.getPaywall(placementId = action.actionId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Get the paywall configuration AdaptyUI.getViewConfiguration(paywall) { result -> when(result) { is AdaptyResult.Success -> { val paywallConfig = result.value // Create and present the paywall val paywallView = AdaptyUI.getPaywallView( activity = this, viewConfig = paywallConfig, products, eventListener = paywallEventListener ) // Add the paywall view to your layout binding.container.addView(paywallView) } is AdaptyResult.Error -> { val error = result.error // handle the error } } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } } ```
Olay örneği (Genişletmek için tıklayın) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
## Onboarding yüklemesinin tamamlanması \{#finishing-loading-onboarding\} Onboarding yüklenmeyi tamamladığında bu metod çağrılır: ```kotlin override fun onFinishLoading(action: AdaptyOnboardingLoadedAction, context: Context) { // Handle loading completion } ```
Olay örneği (Genişletmek için tıklayın) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
## Navigasyon olayları \{#navigation-events\} `onAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır. `event` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `OnboardingStarted` | Onboarding yüklendiğinde | | `ScreenPresented` | Herhangi bir ekran gösterildiğinde | | `ScreenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcının yanıtı) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `SecondScreenPresented` | İkinci ekran gösterildiğinde | | `UserEmailCollected` | Kullanıcının e-posta adresi giriş alanı aracılığıyla toplandığında tetiklenir | | `OnboardingCompleted` | Kullanıcı `final` ID'li bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyaç duyuyorsanız son ekrana `final` ID'sini atayın. | | `Unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veri) içerir | Her olay şu alanları içeren `meta` bilgisi barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Geçerli ekranın tanımlayıcısı | | `screenIndex` | Akıştaki geçerli ekranın konumu | | `totalScreens` | Akıştaki toplam ekran sayısı | Analitik olayları takip etmek için nasıl kullanabileceğinize dair bir örnek: ```kotlin override fun onAnalyticsEvent(event: AdaptyOnboardingAnalyticsEvent, context: Context) { when (event) { is AdaptyOnboardingAnalyticsEvent.OnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingAnalyticsEvent.OnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingAnalyticsEvent.Unknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } ```
Olay örnekleri (Genişletmek için tıklayın) ```javascript // OnboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // ScreenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // ScreenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // SecondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // UserEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // OnboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
--- # File: android-onboarding-input --- --- title: "Android SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Android uygulamanızda onboarding verilerini kaydedin ve kullanın." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları alma](android-get-pb-paywalls) ile [Flow'ları ve paywall'ları gösterme](android-present-paywalls) sayfalarına göz atın. ::: Kullanıcılarınız bir test sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```kotlin override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle single selection } is AdaptyOnboardingStateUpdatedParams.MultiSelect -> { // Handle multiple selections } is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input } is AdaptyOnboardingStateUpdatedParams.DatePicker -> { // Handle date selection } } } ``` Aksiyon formatını [buradan](https://android.adapty.io/adapty-ui/com.adapty.ui.onboardings.actions/-adapty-onboarding-state-updated-action/) inceleyebilirsiniz.
Kaydedilen veri örnekleri (format, implementasyonunuza göre farklılık gösterebilir) ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ```
## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken girilen verileri kullanarak [kullanıcı profilini güncellemeniz](android-setting-user-attributes) gerekir. Örneğin, kullanıcılardan `name` ID'sine sahip metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak ayarlamak istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmelerini de istiyorsunuz. Uygulama kodunuzda bu şu şekilde görünebilir: ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (action.elementId) { "name" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Text -> { builder.withFirstName(inputParams.value) } } } "email" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Email -> { builder.withEmail(inputParams.value) } } } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboardinglardaki quizleri kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara sporla deneyimleri hakkında soru sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding builder'a bir [quiz ekleyin](onboarding-quizzes) ve seçeneklerine anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler belirleyin](android-setting-user-attributes). ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Handle quiz responses and set custom attributes when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (action.elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.params.value) } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` 3. Her özel nitelik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda ilgili placement için [bir paywall gösterin](android-paywalls). Onboardinginizde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](android-handle-onboarding-events#opening-a-paywall) olarak uygulayın. --- # File: android-sdk-call-order --- --- title: "Android SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak kayıp premium erişim, eksik attribution ve aralıklı ADAPTY_NOT_INITIALIZED hatalarından kaçının." --- `Adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağırmamalısınız. Bu tamamlanana kadar SDK'nın hiçbir durumu yoktur. `activate()` öncesinde veya bununla eş zamanlı yapılan her çağrı [`ADAPTY_NOT_INITIALIZED`](android-sdk-error-handling) hatasıyla başarısız olur. Uygulamanız kullanıcıların kimliğini doğruluyorsa ve başlatma sonrasında bir customer user ID topluyorsanız, bu noktada `Adapty.identify()` çağrısı yapın. `identify` tamamlanma callback'i tetiklenene kadar kullanıcı eylemi yöntemlerini çağırmayın. Bununla yarışan çağrılar ya callback'lerinde hata döndürür ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu olduğunda attribution, `appsflyer_id` gibi MMP ID'leri ve kurulum sahipliği tanımlanan profile her zaman aktarılmaz. Uygulamanız kullanıcıların kimliğini doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. Bunları önce başlatın ve `Adapty.activate` çağrısı yapmadan önce UID geri çağrılarını bekleyin. Aksi takdirde MMP ID'si kısa süreli anonim bir profile düşer ve her zaman tanımlanmış profile aktarılmaz. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıralama \{#the-correct-order\} İzleyeceğiniz yol iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK yöntemlerini çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama başlangıcında müşteri kullanıcı kimliğine sahipseniz, `activate()` çağrısından önce bunu `AdaptyConfig.Builder`'a aktarın (2a. adım). Bu yol hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gerekli değildir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlangıcında, ilk olarak | MMP'nin UID geri çağrısını bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `Adapty.activate(context, AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | Uygulama başlangıcında, adım 1'den sonra, müşteri kullanıcı kimliğiniz varsa | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `Adapty.activate(context, AdaptyConfig.Builder("KEY").build())` `customerUserId` olmadan | Uygulama başlangıcında, adım 1'den sonra, müşteri kullanıcı kimliğiniz yoksa (veya hiç toplanmıyorsa) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` | Adım 2'den sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP kimliklerinin doğru profile atanması için gereklidir. | | 4 | `Adapty.identify("YOUR_USER_ID") { error -> ... }` | Adım 3'ten sonra (veya MMP yoksa adım 2'den sonra), adım 5'ten önce — yalnızca kimlik doğrulama ile 2b yolunda | Tamamlama geri çağrısını kullanın. `identify` sırasında eş zamanlı çağrılar anonim profile düşebilir. | | 5 | `getPaywall`, `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız adım 4'ten sonra; aksi hâlde adım 3'ten sonra (veya MMP yoksa adım 2'den sonra) | Bu çağrılar kararlı bir profile ihtiyaç duyar. | :::important Bu adımları atlamak, geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitleye karşı döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar web ödeme sayfasında (Stripe, Paddle) satın alım yapıp ardından uygulamayı yüklerse, cihazdaki ilk `activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Kimlik doğrulama akışınızdan veya install referrer'dan uygulama başlamadan önce kullanıcı ID'sini çözümleyebiliyorsanız, doğrudan `AdaptyConfig.Builder` içinde belirtin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` ve ardından `restorePurchases` çağrısı yapılana kadar cihazda görünmez. Her web ödeme sayfasıyla göndereceğiniz metadata için şu sayfalara bakın: - [Stripe](stripe) - [Paddle](paddle) --- # File: android-optimize-paywall-fetching --- --- title: "Android SDK'da paywall çekmeyi optimize etme" description: "Adapty paywalllarını güvenilir şekilde çekin: Android için zamanlama, önbellekleme ve yedek kalıplar." --- Android'de güvenilir bir paywall çekme işlemi üç şeyi yapar: hızlı render eder, kitleye hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz biçimde yedek gösterir. Aşağıdaki kurallar bu hedefe ulaşmak için gereken zamanlama, önbellekleme ve yedek kalıpları kapsar. :::tip Bu kurallar, `Adapty.activate()` ve `Adapty.identify()` işlevlerinin zaten tamamlandığını varsayar. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). ::: ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Bunu yapın | Bunu yapmayın | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı getirin. | Başlatma sırasında tüm placement'ları eş zamanlı olarak önceden getirin. | Toplu ön getirme ana thread'i bloke eder ve bu sürede siyah ekran görünür. | | `getPaywall`'ı attribution çözümlenme şansı bulduktan sonra çağırın — örneğin `activate`'ten 1-2 saniye sonra veya `setOnProfileUpdatedListener` tetiklendikten sonra. | `getPaywall`'ı `Application.onCreate()` içinde çağırın. | Attribution henüz gelmemiştir. Paywall varsayılan kitleye göre çözümlenir ve segment ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` ayarlayın ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ı süresiz olarak bekleyin. | Zaman aşımı olmadan, zayıf bağlantıdaki kullanıcılar ağ çözümlenene kadar boş ekran görür ya da uygulamayı kapatır. | `fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products-android) sayfasına, doğru placement seçimi için ise [Placement'lar](placements) sayfasına bakın. ## Zayıf bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantı yaşanan pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunlarından etkilenen bölgeler): - İlk fetch dışındaki her fetch işleminde `fetchPolicy` değerini `AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad` olarak ayarlayın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalla geçin. - Paywall gösterimini `getProfile`'a bağlamayın. `getPaywall` fonksiyonunu bağımsız olarak çağırın; böylece yavaş bir profil yüklenmesi arayüzü bloke etmez. --- # File: android-test --- --- title: "Android SDK'da test ve yayınlama" description: "Adapty ile Android uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Adapty SDK'yı Android uygulamanıza zaten entegre ettiyseniz, her şeyin doğru şekilde kurulduğunu ve satın almaların beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de Google Play'in sandbox ortamıyla gerçek satın alma akışını test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Sandbox testi ve kapalı iz doğrulaması dahil olmak üzere uygulama içi satın almalarınızı kapsamlı biçimde test etmek için [test rehberimize](testing-on-android) bakın. ## Yayın öncesi hazırlık \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesini](release-checklist) takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'ye raporlanıyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanmış --- # File: android-sdk-error-handling --- --- title: "Android SDK'da hataları yönetin" description: "Adapty'nin sorun giderme rehberiyle Android SDK hatalarını etkili bir şekilde yönetin." --- SDK tarafından döndürülen her hata `AdaptyError` türündedir. :::tip **Hata ayıklamadan önce ayrıntılı logları etkinleştirin.** Çoğu `AdaptyError`, temel bir Play Billing, ağ veya backend hatasını sarmalıyor. Ayrıntılı loglar açıkken (`Adapty.logLevel = AdaptyLogLevel.VERBOSE` — bkz. [Loglama](sdk-installation-android#logging)), sarmalanan hata konsola yazdırılır ve genellikle asıl nedeni ortaya koyar. ::: :::important Bu çözümler sorununuzu gidermezse, destek ekibiyle iletişime geçmeden önce atmanız gereken adımlar için [Diğer sorunlar](#other-issues) bölümüne bakın; bu sayede size daha verimli yardım edebiliriz. ::: | Hata | Çözüm | |----------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | UNKNOWN | Bu hata, bilinmeyen veya beklenmedik bir hata oluştuğunu gösterir. | | [ITEM_UNAVAILABLE](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_UNAVAILABLE()) | Bu hata çoğunlukla test aşamasında ortaya çıkar. Ürünlerin production'da bulunmadığı ya da kullanıcının Google Play'deki Testers grubuna dahil olmadığı anlamına gelebilir. | | ADAPTY_NOT_INITIALIZED | Adapty SDK etkinleştirilmemiş.
En sık, splash screen veya erken çalışan bir UI bileşeninin `Adapty.activate` tamamlanmadan önce Adapty metodlarını çağırmasından kaynaklanır. Gerçek cihaz zamanlaması emülatörden farklı olduğu için bu sorun aralıklı olarak ortaya çıkabilir ve emülatörde yeniden üretilmeyebilir. Başka SDK çağrılarını planlamadan önce `Adapty.activate` tamamlanmasını bekleyin. Tam sıra için [Android SDK'da çağrı sırası](android-sdk-call-order) konusuna bakın. Ayrıca `Adapty.activate` metoduyla [Adapty SDK'yı doğru şekilde yapılandırmanız](sdk-installation-android#activate-adapty-module-of-adapty-sdk) gerekir. | | PROFILE_WAS_CHANGED | İşlem sırasında kullanıcı profili değiştirildi.
Bu durum, `Adapty.identify` hâlâ devam ederken başka bir metod çağrıldığında yaşanır; devam eden çağrı değiştirilmek üzere olan bir profile denk gelir ve SDK onu reddeder. Diğer SDK çağrılarını planlamadan önce `Adapty.identify` tamamlanmasını bekleyin. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). | | PRODUCT_NOT_FOUND | Bu hata, satın alınmak istenen ürünün mağazada mevcut olmadığını gösterir. | | INVALID_JSON |

Yerel yedek paywall JSON'ı geçerli değil.

Önce varsayılan İngilizce paywallınızı düzeltin, ardından geçersiz yerel paywallları değiştirin. Bir paywallın nasıl düzeltileceğine dair ayrıntılar için [Paywall'ı remote config ile özelleştirme](customize-paywall-with-remote-config) konusuna, yerel paywallların nasıl değiştirileceğine dair ayrıntılar için ise [Yerel yedek paywallları tanımlama](fallback-paywalls) konusuna bakın.

| |

CURRENT_SUBSCRIPTION_TO_UPDATE

\_NOT_FOUND_IN_HISTORY

| Değiştirilmesi gereken orijinal abonelik, aktif abonelikler arasında bulunamadı. | | [BILLING_SERVICE_TIMEOUT](https://developer.android.com/google/play/billing/errors#service_timeout_error_code_-3) | Bu hata, Google Play yanıt veremeden isteğin maksimum zaman aşımına ulaştığını gösterir. Örneğin, Play Billing Library çağrısının talep ettiği işlemin gecikmesinden kaynaklanabilir. | | [FEATURE_NOT_SUPPORTED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#FEATURE_NOT_SUPPORTED()) | İstenen özellik, mevcut cihazda Play Store tarafından desteklenmiyor. | | [BILLING_SERVICE_DISCONNECTED](https://developer.android.com/google/play/billing/errors#service_disconnected_error_code_-1) | Bu hata, istemci uygulamanın `BillingClient` aracılığıyla Google Play Store hizmetiyle kurduğu bağlantının kesildiğini gösterir. | | [BILLING_SERVICE_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#service_unavailable_error_code_2) | Bu hata, Google Play Billing hizmetinin şu anda kullanılamaz durumda olduğunu gösterir. Çoğu durumda bu, istemci cihaz ile Google Play Billing hizmetleri arasındaki bir noktada ağ bağlantısı sorunu olduğu anlamına gelir. | | [BILLING_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) |

Bu hata, satın alma işlemi sırasında bir faturalandırma sorunu oluştuğunu gösterir. Olası nedenler şunlardır:

1. Kullanıcının cihazındaki Play Store uygulaması eksik veya güncel değil.

2. Kullanıcı desteklenmeyen bir ülkede.

3. Kullanıcı, yöneticinin satın almaları devre dışı bıraktığı bir kurumsal hesabın parçası.

4. Google Play, kullanıcının ödeme yöntemini tahsil edemedi (örneğin süresi dolmuş bir kredi kartı).

5. Kullanıcı Play Store uygulamasında oturum açmamış.

| | [DEVELOPER_ERROR](https://developer.android.com/google/play/billing/errors#developer_error) | Bu hata, bir API'nin hatalı kullanıldığını gösterir. | | [BILLING_ERROR](https://developer.android.com/google/play/billing/errors#error_error_code_6) | Bu hata, Google Play'in kendi içinde bir sorun olduğunu gösterir. | | [ITEM_ALREADY_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_ALREADY_OWNED()) | Ürün zaten satın alınmış. | | [ITEM_NOT_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_NOT_OWNED()) | Bu hata, kullanıcının ürüne sahip olmadığı için istenen işlemin gerçekleştirilemediğini gösterir. | | [BILLING_NETWORK_ERROR](https://developer.android.com/google/play/billing/errors#network_error_error_code_12) | Bu hata, cihaz ile Play sistemleri arasındaki ağ bağlantısında bir sorun olduğunu gösterir. | | NO_PRODUCT_IDS_FOUND |

Bu hata, paywallda yer alan ürünlerin hiçbirinin mağazada mevcut olmadığını gösterir.

Bu hatayla karşılaşıyorsanız sorunu çözmek için aşağıdaki adımları izleyin:

  1. Tüm ürünlerin Adapty Kontrol Paneli'ne eklenip eklenmediğini kontrol edin.
  2. Uygulamanızın **Package name** değerinin Google Play Console'daki ile eşleştiğinden emin olun.
  3. Uygulama mağazalarındaki ürün tanımlayıcılarının Kontrol Paneli'ne eklediğiniz tanımlayıcılarla örtüştüğünü doğrulayın. Tanımlayıcıların Bundle ID içermemesi gerektiğini unutmayın; Bundle ID zaten mağazada dahilse bu kural uygulanmaz.
  4. Google vergi ayarlarınızda uygulamanın ödeme durumunun **Active** olduğunu onaylayın. Vergi bilgilerinizin güncel ve sertifikalarınızın geçerli olduğundan emin olun.
  5. Uygulamaya bir banka hesabının bağlı olup olmadığını kontrol edin; bu, uygulamanın para kazanmaya uygun olması için gereklidir.
  6. Ürünlerin bulunduğunuz bölgede kullanılabilir olup olmadığını kontrol edin.
  7. Uygulamanızın test kanallarından birinde olduğundan emin olun. **Internal testing** kanalı inceleme gerektirmediği ve uygulamayı müşterilerden gizli tuttuğu için en kolay seçenektir.
| | NO_PURCHASES_TO_RESTORE | Bu hata, Google Play'in geri yüklenecek satın alma işlemi bulamadığını gösterir. | | AUTHENTICATION_ERROR | `Adapty.activate` metoduyla [Adapty SDK'yı doğru şekilde yapılandırmanız](sdk-installation-android#activate-adapty-module-of-adapty-sdk) gerekiyor. | | BAD_REQUEST | Hatalı istek.
[Google Play ile entegrasyon](google-play-store-connection-configuration) için gerekli tüm adımları tamamladığınızdan emin olun. | | SERVER_ERROR | Sunucu hatası. | | REQUEST_FAILED | Bu hata, düzgün tanımlanamayan bir ağ sorununu gösterir. | | DECODING_FAILED | Yanıt çözümlenemedi.
Kodunuzu gözden geçirin ve gönderdiğiniz parametrelerin geçerli olduğundan emin olun. Örneğin bu hata, geçersiz bir API anahtarı kullandığınıza işaret edebilir. | | ANALYTICS_DISABLED | [Devre dışı bıraktığınız](analytics-integration#disabling-external-analytics-for-a-specific-customer) için analytics etkinliklerini işleyemiyoruz. | | WRONG_PARAMETER | Bu hata, bazı parametrelerinizin hatalı olduğunu gösterir: boş olamayacak bir alan boş bırakılmış ya da yanlış tür kullanılmış vb. | ## Diğer sorunlar \{#other-issues\} Henüz bir çözüm bulamadıysanız, sonraki adımlar şunlar olabilir: - **SDK'yı en son sürüme yükseltme**: En son SDK sürümleri daha kararlıdır ve bilinen sorunlara yönelik düzeltmeler içerir; bu nedenle her zaman güncellemenizi öneririz. - **Destek ekibiyle iletişime geçin veya diğer geliştiricilerden yardım alın** [destek forumunda](https://adapty.featurebase.app/). - **Destek ekibiyle [support@adapty.io](mailto:support@adapty.io) adresinden veya sohbet üzerinden iletişime geçin**: SDK'yı yükseltmeye hazır değilseniz ya da yükseltme sorunu çözmediyse destek ekibimize ulaşın. [Ayrıntılı günlük kaydını etkinleştirip](sdk-installation-android#logging) günlükleri ekiple paylaşırsanız sorununuz daha hızlı çözülür. İlgili kod parçacıklarını da ekleyebilirsiniz. --- # File: migration-to-android-sdk-v4 --- --- title: "Adapty Android SDK'yı v. 4.0'a Geçirme" description: "Adapty Android SDK v4.0'a geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty Android SDK 4.0, flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır; Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı referans \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty.getPaywall(placementId, locale)` | `Adapty.getFlow(placementId)` | | `Adapty.getPaywallForDefaultAudience(placementId, locale)` | `Adapty.getFlowForDefaultAudience(placementId)` | | `AdaptyUI.getViewConfiguration(paywall)` | `AdaptyUI.getFlowConfiguration(flow, locale)` | | `AdaptyUI.LocalizedViewConfiguration` | `AdaptyUI.FlowConfiguration` | | `Adapty.getPaywallProducts(paywall)` | `Adapty.getPaywallProducts(flow)` | | `Adapty.logShowPaywall(paywall)` | `Adapty.logShowFlow(flow)` | | `AdaptyPaywall` | `AdaptyFlow` | | `AdaptyUI.getPaywallView(...)` | `AdaptyUI.getFlowView(...)` | | `AdaptyPaywallView` | `AdaptyFlowView` | | `AdaptyPaywallScreen` (Compose) | `AdaptyFlowScreen` | | `showPaywall(...)` | `showFlow(...)` | | `AdaptyPaywallInsets` | `AdaptyFlowInsets` | | `AdaptyUiEventListener` | `AdaptyFlowEventListener` | | `AdaptyUiDefaultEventListener` | `AdaptyFlowDefaultEventListener` | | `onPaywallShown` / `onPaywallClosed` | `onFlowShown` / `onFlowClosed` | | `onRenderingError` | `onError` | | `Adapty.updateAttribution(attribution, source)` (`source: String`) | `Adapty.updateAttribution(attribution, source)` (`source: AdaptyAttributionSource`) | | `Adapty.setIntegrationIdentifier(key, value)` | `Adapty.setIntegrationIdentifier(AdaptyIntegrationIdentifier)` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` artık bir `AdaptyFlow` alır. Diğer `AdaptyFlowEventListener` metotları (`onProductSelected`, `onPurchaseStarted`, `onPurchaseFinished`, `onPurchaseFailure`, `onRestoreSuccess`, `onRestoreFailure`, `onActionPerformed`, `onAwaitingPurchaseParams`, `onLoadingProductsFailure` ve diğerleri) adlarını ve imzalarını korur. ## Kurulum \{#installation\} `adapty-bom` sürümünü `4.0.0` (veya daha yenisi) olarak ayarlayın ve projeyi senkronize edin. BOM, sizin için uygun `android-sdk` ve `android-ui` sürümlerini otomatik olarak belirler. Bağımlılık tanımlamaları için [Adapty SDK'yı Yükleyin](sdk-installation-android) sayfasına bakın. ## Kaldırılan ve kullanımdan kaldırılan API'ler \{#removed-and-deprecated-apis\} - **`Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized, callback)`** — kaldırıldı. Bu aşırı yükleme v3'te kullanımdan kaldırılmıştı. Aynı seçenekleri bunun yerine `AdaptyPurchaseParameters` üzerinden iletin: ```diff showLineNumbers - Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized) { result -> /* ... */ } + val params = AdaptyPurchaseParameters.Builder() + .withSubscriptionUpdateParams(subscriptionUpdateParams) + .withOfferPersonalized(isOfferPersonalized) + .build() + Adapty.makePurchase(activity, product, params) { result -> /* ... */ } ``` - **Onboardinglar artık kullanım dışı.** `AdaptyUI.getOnboardingView` ve `AdaptyUI.getOnboardingConfiguration`, 4.0'da `@Deprecated` olarak işaretlendi — onboardinglarınızı [Flow Builder](adapty-flow-builder)'da oluşturulan flow'lara taşıyın. ## Flow'ları getirme \{#fetching-flows\} ### getPaywall + getViewConfiguration → getFlow + getFlowConfiguration Getirme işleminin dönüş türü `AdaptyPaywall`'dan `AdaptyFlow`'a değişiyor; yapılandırma yükleyicisi ise `AdaptyUI.getViewConfiguration`'dan `AdaptyUI.getFlowConfiguration`'a yeniden adlandırılıyor (`AdaptyUI.LocalizedViewConfiguration` yerine `AdaptyUI.FlowConfiguration` döndürüyor). `locale` parametresi, getirme çağrısından `getFlowConfiguration`'a taşınıyor: ```diff showLineNumbers - Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result -> + Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> if (result is AdaptyResult.Success) { - val paywall = result.value - if (!paywall.hasViewConfiguration) return@getPaywall - AdaptyUI.getViewConfiguration(paywall) { configResult -> + val flow = result.value + if (!flow.hasViewConfiguration) return@getFlow + AdaptyUI.getFlowConfiguration(flow, locale = "en") { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value } } } } ``` ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` artık `Adapty.getFlow` tarafından döndürülen bir `AdaptyFlow` alıyor: ```diff showLineNumbers - Adapty.getPaywallProducts(paywall) { result -> /* products */ } + Adapty.getPaywallProducts(flow) { result -> /* products */ } ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık `AdaptyPaywall` yerine `AdaptyFlow` alıyor. Etkinlik hâlâ aynı varyasyona karşı kaydedildiğinden, mevcut huni ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder. ```diff showLineNumbers - Adapty.logShowPaywall(paywall) + Adapty.logShowFlow(flow) ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülerken bu metodu çağırmanıza gerek yoktur — Adapty bu görüntülemeleri otomatik olarak takip eder. ## Flow'ları görüntüleme \{#displaying-flows\} ### getPaywallView / AdaptyPaywallView → getFlowView / AdaptyFlowView Factory metodunu ve view türünü yeniden adlandırın, ardından `AdaptyUI.FlowConfiguration`'ı geçirin: ```diff showLineNumbers - val paywallView = AdaptyUI.getPaywallView( - activity, - viewConfiguration, - products, - eventListener, - ) + val flowView = AdaptyUI.getFlowView( + activity, + flowConfiguration, + products, + eventListener, + ) ``` View'ı doğrudan oluşturuyorsanız, show metodu da yeniden adlandırılmıştır: ```diff showLineNumbers - val paywallView = AdaptyPaywallView(activity) - paywallView.showPaywall(viewConfiguration, products, eventListener) + val flowView = AdaptyFlowView(activity) + flowView.showFlow(flowConfiguration, products, eventListener) ``` XML layout'larında view tag'ini güncelleyin: ```diff showLineNumbers - + ``` İsteğe bağlı `personalizedOfferResolver` parametresi `getFlowView` / `showFlow` / `AdaptyFlowScreen`'den kaldırıldı. Kişiselleştirilmiş fiyatlandırmayı belirtmek için `onAwaitingPurchaseParams` aracılığıyla her ürün için ayrı ayrı ayarlayın (`AdaptyPurchaseParameters.Builder().withOfferPersonalized(true)`). Yeni isteğe bağlı `customAssets` parametresi, görselleri ve videoları çalışma zamanında geçersiz kılmanıza olanak tanır — bkz. [Özel asset'ler](android-get-pb-paywalls#customize-assets). ### AdaptyPaywallScreen → AdaptyFlowScreen Jetpack Compose'da composable'ı yeniden adlandırın ve konfigürasyon parametresini güncelleyin: ```diff showLineNumbers - AdaptyPaywallScreen( - viewConfiguration, + AdaptyFlowScreen( + flowConfiguration, products, eventListener, ) ``` ## Olayları Yönetme \{#handling-events\} Olay dinleyicisi `AdaptyUiEventListener`'dan `AdaptyFlowEventListener`'a (ve `AdaptyUiDefaultEventListener`'dan `AdaptyFlowDefaultEventListener`'a) yeniden adlandırıldı. Metot adlarının çoğu değişmedi; yaşam döngüsü ve render callback'leri yeniden adlandırıldı: ```diff showLineNumbers - class YourListener : AdaptyUiDefaultEventListener() { + class YourListener : AdaptyFlowDefaultEventListener() { - override fun onPaywallShown(context: Context) {} - override fun onPaywallClosed() {} + override fun onFlowShown(context: Context) {} + override fun onFlowClosed() {} - override fun onRenderingError(error: AdaptyError, context: Context) {} + override fun onError(error: AdaptyError, context: Context) {} } ``` Mevcut handler gövdelerinde kod değişikliği gerekmez — sadece türü ve override'ları yeniden adlandırın. `onError`, `onRenderingError`'ın tetiklendiği rendering hatalarının yanı sıra diğer satın alma dışı runtime hatalarında da tetiklenir. Callback'lerin tam listesi için bkz. [Flow & paywall olaylarını yönetme](android-handling-events). v4 ayrıca bir `onBackPressed(context): Boolean` callback'i ekler ve varsayılan davranışı sistem geri tuşunun nasıl çalıştığını değiştirir. Önceden geri tuşuna basmak (veya geri gesturı) aktivitenize ya da fragment'ınıza geçer ve genellikle paywall'ı kapatırdı. v4'te varsayılan uygulama bu basışı tüketir; dolayısıyla **sistem geri tuşu artık bir flow'u kendi başına kapatmaz** — flow'un sistem gesturıyla kapatılamadığı iOS davranışıyla aynı hizaya gelir. Kullanıcılara açık bir çıkış yolu sunun (bir **Close** düğmesi veya bir `on_device_back` aksiyonu) ya da eski davranışı geri kazanmak için `onBackPressed`'i `false` döndürecek şekilde geçersiz kılın. Ayrıntılar için [Sistem geri tuşu](android-handling-events#system-back-button) bölümüne bakın. Varsayılan satın alma işleyicisi artık ekranı kapatmayı da durduruyor. v3'te, varsayılan `onPurchaseFinished`, kullanıcının iptal etmediği her tamamlanmış satın almanın (başarılı veya beklemedeki satın alma) ardından paywallı kapatıyordu. v4'te bu işlem hiçbir şey yapmıyor, dolayısıyla **siz kapatana kadar bir flow, satın alma sonrasında açık kalıyor** — bu da iOS davranışıyla örtüşüyor. Bu otomatik kapanmaya güveniyorsanız, satın alma tamamlandığında ekranı kendiniz kapatın. Örnek için [Başarılı, iptal edilmiş veya beklemedeki satın alma](android-handling-events#successful-canceled-or-pending-purchase) konusuna bakın. ## Attribution ve entegrasyon tanımlayıcıları \{#attribution-and-integration-identifiers\} ### updateAttribution `source` parametresi `String` türünden yeni `AdaptyAttributionSource` türüne değişti ve `attribution` artık `Map` türünde (JSON `String` aşırı yüklemesi de mevcuttur). Önceden tanımlanmış kaynaklardan birini kullanın: ```diff showLineNumbers - Adapty.updateAttribution(attribution, "appsflyer") { error -> /* handle the error */ } + Adapty.updateAttribution(attribution, AdaptyAttributionSource.APPSFLYER) { error -> /* handle the error */ } ``` Önceden tanımlanmış kaynaklar: `AdaptyAttributionSource.APPLE_ADS`, `.ADJUST`, `.APPSFLYER`, `.BRANCH`, `.TENJIN`. Diğer kaynaklar için bir dizeden oluşturun: `AdaptyAttributionSource("your_source")`. ### setIntegrationIdentifier `setIntegrationIdentifier(key, value)`, bir veya daha fazla `AdaptyIntegrationIdentifier` değeri alan bir yöntemle değiştirilmiştir. Ham bir string key geçirmek yerine, her tanımlayıcıyı bir kolaylık yöntemiyle oluşturun: ```diff showLineNumbers - Adapty.setIntegrationIdentifier("appsflyer_id", appsFlyerId) { error -> /* handle the error */ } + Adapty.setIntegrationIdentifier(AdaptyIntegrationIdentifier.appsflyerId(appsFlyerId)) { error -> /* handle the error */ } ``` Tek bir çağrıda birden fazla tanımlayıcı ayarlayabilirsiniz: ```kotlin showLineNumbers Adapty.setIntegrationIdentifier( listOf( AdaptyIntegrationIdentifier.appsflyerId(appsFlyerId), AdaptyIntegrationIdentifier.adjustDeviceId(adjustDeviceId), ) ) { error -> /* handle the error */ } ``` Eski her anahtar dizesini ilgili kolaylık metoduyla değiştirin: | v3 anahtarı | v4 `AdaptyIntegrationIdentifier` metodu | |---|---| | `"adjust_device_id"` | `adjustDeviceId(value)` | | `"airbridge_device_id"` | `airbridgeDeviceId(value)` | | `"amplitude_user_id"` | `amplitudeUserId(value)` | | `"amplitude_device_id"` | `amplitudeDeviceId(value)` | | `"appmetrica_device_id"` | `appmetricaDeviceId(value)` | | `"appmetrica_profile_id"` | `appmetricaProfileId(value)` | | `"appsflyer_id"` | `appsflyerId(value)` | | `"branch_id"` | `branchId(value)` | | `"facebook_anonymous_id"` | `facebookAnonymousId(value)` | | `"firebase_app_instance_id"` | `firebaseAppInstanceId(value)` | | `"mixpanel_user_id"` | `mixpanelUserId(value)` | | `"one_signal_subscription_id"` | `oneSignalSubscriptionId(value)` | | `"one_signal_player_id"` | `oneSignalPlayerId(value)` | | `"posthog_distinct_user_id"` | `posthogDistinctUserId(value)` | | `"pushwoosh_hwid"` | `pushwooshHWID(value)` | | `"tenjin_analytics_installation_id"` | `tenjinAnalyticsInstallationId(value)` | `AdaptyIntegrationIdentifier(AdaptyIntegrationIdentifier.Key("custom"), customValue)` şeklinde özel bir `Key` kullanarak bu listede olmayan bir anahtar için identifier'ı doğrudan oluşturabilirsiniz. --- # File: migration-to-android-312 --- --- title: "Adapty Android SDK'yı v3.12'ye Taşıma" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Android SDK v3.12'ye geçiş yapın." --- Adapty SDK 3.12.0'da `logShowOnboarding` metodunu SDK'dan kaldırdık. Bu metodu kullanıyorsanız, SDK'yı 3.12 veya sonraki bir sürüme yükselttiğinizde artık kullanılamayacak. Bunun yerine, [Adapty'nin kodsuz onboarding oluşturucusunda onboarding'ler oluşturabilirsiniz](onboardings). Bu onboarding'lerin analitikleri otomatik olarak takip edilir ve pek çok özelleştirme seçeneğine sahipsiniz. --- # File: migration-to-android-310 --- --- title: "Android Adapty SDK 3.10.0 için Geçiş Rehberi" description: "" --- Adapty SDK 3.10.0, bazı iyileştirmeler getiren büyük bir sürümdür; ancak bu iyileştirmeler sizden birkaç geçiş adımı gerektirebilir: 1. `AdaptyUiPersonalizedOfferResolver` kaldırıldı. Eğer bunu kullanıyorsanız, `onAwaitingPurchaseParams` callback'inde geçirin. 2. Paywall Builder paywallları için `onAwaitingSubscriptionUpdateParams` metod imzasını güncelleyin. ## Satın alma parametreleri callback'ini güncelleme \{#update-purchase-parameters-callback\} `onAwaitingSubscriptionUpdateParams` metodu `onAwaitingPurchaseParams` olarak yeniden adlandırıldı ve artık `AdaptySubscriptionUpdateParameters` yerine `AdaptyPurchaseParameters` kullanıyor. Bu sayede abonelik değiştirme parametrelerini (crossgrade) belirtebilir, fiyatın kişiselleştirilmiş olup olmadığını ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) işaretleyebilir ve diğer satın alma parametrelerini yapılandırabilirsiniz. ```diff showLineNumbers - override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, - ) { - onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) - } + override fun onAwaitingPurchaseParams( + product: AdaptyPaywallProduct, + context: Context, + onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, + ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { + onPurchaseParamsReceived( + AdaptyPurchaseParameters.Builder() + .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) + .withOfferPersonalized(true) + .build() + ) + return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked + } ``` Ek parametreye ihtiyaç duymuyorsanız şunu kullanabilirsiniz: ```kotlin showLineNumbers + override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` --- # File: migration-to-android-sdk-34 --- --- title: "Adapty Android SDK'sını v3.4'e Taşıma" description: "Daha iyi performans ve yeni gelir getirici özellikler için Adapty Android SDK v3.4'e geçin." --- Adapty SDK 3.4.0, tarafınızda geçiş adımları gerektiren iyileştirmeler sunan büyük bir sürümdür. ## Yedek paywall dosyalarını güncelleyin \{#update-fallback-paywall-files\} Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki [mevcut yedek paywallları yeni dosyalarla değiştirin](android-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleyin \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Önceki sürümlerde, Adapty'nin kendi altyapınız üzerinden gerçekleştirilen işlemleri tanıyabilmesi için satın almaları geri yüklemeniz gerekiyordu; çünkü Observer Mode'da Adapty bu işlemlere doğrudan erişemiyordu. Paywall kullanıyorsanız her işlemi başlatan paywall ile elle ilişkilendirmeniz de gerekiyordu. Yeni sürümde, Adapty'nin her işlemi tanıyabilmesi için açıkça bildirmeniz gerekir. Paywall kullanıyorsanız, işlemi kullanılan paywall ile ilişkilendirmek için variation ID'yi de iletmeniz gerekir. :::warning **İşlem raporlamayı atlamayın!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - Adapty.restorePurchases { result -> - if (result is AdaptyResult.Success) { - // success - } - } - - Adapty.setVariationId(transactionId, variationId) { error -> - if (error == null) { - // success - } - } + val transactionInfo = TransactionInfo.fromPurchase(purchase) + + Adapty.reportTransaction(transactionInfo, variationId) { result -> + if (result is AdaptyResult.Success) { + // success + } + } ``` ```diff showLineNumbers - Adapty.restorePurchases(result -> { - if (result instanceof AdaptyResult.Success) { - // success - } - }); - - Adapty.setVariationId(transactionId, variationId, error -> { - if (error == null) { - // success - } - }); + TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); + + Adapty.reportTransaction(transactionInfo, variationId, result -> { + if (result instanceof AdaptyResult.Success) { + // success + } + }); ``` --- # File: migration-to-android330 --- --- title: "Adapty Android SDK'yı v3.3'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Android SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.0, bazı iyileştirmeler getiren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Paywall Builder ile oluşturulmayan paywall'larda satın alma işlemlerini nasıl ele aldığınızı güncelleyin. `USER_CANCELED` ve `PENDING_PURCHASE` hata kodlarını işlemeyi bırakın. İptal edilen bir satın alma artık hata olarak kabul edilmez ve hata olmayan satın alma sonuçlarında görünecektir. 2. Paywall Builder ile oluşturulan paywall'lar için `onPurchaseCanceled` ve `onPurchaseSuccess` olaylarını yeni `onPurchaseFinished` olayıyla değiştirin. Bu değişiklik aynı nedenle yapılmaktadır: iptal edilen satın almalar artık hata olarak değerlendirilmez ve hata olmayan satın alma sonuçlarına dahil edilir. 3. Paywall Builder paywallları için `onAwaitingSubscriptionUpdateParams` metot imzasını değiştirin. 4. Dosya URI'sini doğrudan geçiriyorsanız yedek paywall sağlamak için kullanılan metodu güncelleyin. 5. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. ## Satın alma işlemini güncelleme \{#update-making-purchase\} Daha önce iptal edilen ve beklemedeki satın almalar hata olarak değerlendirilir ve sırasıyla `USER_CANCELED` ve `PENDING_PURCHASE` kodları döndürülürdü. Artık iptal edilen, başarılı ve beklemedeki satın almaları belirtmek için yeni bir `AdaptyPurchaseResult` sınıfı kullanılmaktadır. Satın alma kodunu aşağıdaki şekilde güncelleyin: ~~~diff Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { - val info = result.value - val profile = info?.profile - - if (profile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true) { - // Grant access to the paid features - } + when (val purchaseResult = result.value) { + is AdaptyPurchaseResult.Success -> { + val profile = purchaseResult.profile + if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { + // Grant access to the paid features + } + } + + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash + } + } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ~~~ Tam kod örneği için [Mobil uygulamada satın alma yapma](android-making-purchases#make-purchase) sayfasına göz atın. ## Paywall Builder satın alma olaylarını değiştirme \{#modify-paywall-builder-purchase-events\} 1. `onPurchaseFinished` olayı ekleyin: ```diff showLineNumbers + public override fun onPurchaseFinished( + purchaseResult: AdaptyPurchaseResult, + product: AdaptyPaywallProduct, + context: Context, + ) { + when (purchaseResult) { + is AdaptyPurchaseResult.Success -> { + // Grant access to the paid features + } + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash) + } + } + } ``` Tam kod örneği için [Başarılı, iptal edilen veya beklemedeki satın alma](android-handling-events#successful-canceled-or-pending-purchase) bölümüne ve olay açıklamasına bakın. 2. `onPurchaseCancelled` olayının işlenmesini kaldırın: ```diff showLineNumbers - public override fun onPurchaseCanceled( - product: AdaptyPaywallProduct, - context: Context, - ) {} ``` 3. `onPurchaseSuccess` ifadesini kaldırın: ```diff showLineNumbers - public override fun onPurchaseSuccess( - profile: AdaptyProfile?, - product: AdaptyPaywallProduct, - context: Context, - ) { - // Your logic on successful purchase - } ``` ## `onAwaitingSubscriptionUpdateParams` metodunun imzasını değiştirin \{#change-the-signature-of--onawaitingsubscriptionupdateparams-method\} Artık başka bir abonelik aktifken yeni bir abonelik satın alınırsa, yeni aboneliğin mevcut aktif aboneliğin yerini alması gerekiyorsa `onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters...))` çağırın; aktif aboneliğin yerinde kalması ve yeni aboneliğin ayrı olarak eklenmesi gerekiyorsa `onSubscriptionUpdateParamsReceived(null)` çağırın: ```diff showLineNumbers - public override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - ): AdaptySubscriptionUpdateParameters? { - return AdaptySubscriptionUpdateParameters(...) - } + public override fun onAwaitingSubscriptionUpdateParams( + product: AdaptyPaywallProduct, + context: Context, + onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, + ) { + onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) + } ``` [Yükseltme aboneliği](android-handling-events#upgrade-subscription) doküman bölümüne bakarak son kod örneğini inceleyebilirsiniz. ## Yedek paywall'ları güncelleme \{#update-providing-fallback-paywalls\} Yedek paywall'ları sağlamak için dosya URI'si kullanıyorsanız, bunu aşağıdaki şekilde güncelleyin: ```diff showLineNumbers val fileUri: Uri = // Get the URI for the file with fallback paywalls - Adapty.setFallbackPaywalls(fileUri, callback) + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback) ``` ```diff showLineNumbers Uri fileUri = // Yedek paywall'lar için dosyanın URI'sını al - Adapty.setFallbackPaywalls(fileUri, callback); + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback); ``` ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleme \{#update-third-party-integration-sdk-configuration\} Adapty Android SDK 3.3.0 ve sonraki sürümlerle entegrasyonların düzgün çalışmasını sağlamak için aşağıdaki bölümlerde açıklandığı şekilde entegrasyon SDK yapılandırmalarınızı güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. ```diff showLineNumbers - Adjust.getAttribution { attribution -> - if (attribution == null) return@getAttribution - - Adjust.getAdid { adid -> - if (adid == null) return@getAdid - - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST, adid) { error -> - // Handle the error - } - } - } + Adjust.getAdid { adid -> + if (adid == null) return@getAdid + + Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error -> + if (error != null) { + // Handle the error + } + } + } + + Adjust.getAttribution { attribution -> + if (attribution == null) return@getAttribution + + Adapty.updateAttribution(attribution, "adjust") { error -> + if (error != null) { + // Handle the error + } + } + } ``` ```diff showLineNumbers val config = AdjustConfig(context, adjustAppToken, environment) config.setOnAttributionChangedListener { attribution -> attribution?.let { attribution -> - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST) { error -> + Adapty.updateAttribution(attribution, "adjust") { error -> if (error != null) { // Handle the error } } } } Adjust.onCreate(config) ``` ### AirBridge Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge) bölümüne bakın. ```diff showLineNumbers Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback() { override fun onSuccess(result: String) { - val params = AdaptyProfileParameters.Builder() - .withAirbridgeDeviceId(result) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error -> + if (error != null) { + // Handle the error + } + } } override fun onFailure(throwable: Throwable) { } }) ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) bölümüne bakın. ```diff showLineNumbers // For Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeDeviceId = amplitude.store.deviceId val amplitudeUserId = amplitude.store.userId // - val params = AdaptyProfileParameters.Builder() - .withAmplitudeDeviceId(amplitudeDeviceId) - .withAmplitudeUserId(amplitudeUserId) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### AppMetrica Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppMetrica entegrasyonu için SDK yapılandırması](appmetrica#sdk-configuration) sayfasına bakın. ```diff showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceId = result?.deviceId ?: return - val params = AdaptyProfileParameters.Builder() - .withAppmetricaDeviceId(deviceId) - .withAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID") - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId) { error -> + if (error != null) { + // Handle the error + } + } + + Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error -> + if (error != null) { + // Handle the error + } + } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { // Handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID)) ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) sayfasına bakın. ```diff showLineNumbers val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener { override fun onConversionDataSuccess(conversionData: Map) { - Adapty.updateAttribution( - conversionData, - AdaptyAttributionSource.APPSFLYER, - AppsFlyerLib.getInstance().getAppsFlyerUID(context) - ) { error -> - if (error != null) { - // Handle the error - } - } + val uid = AppsFlyerLib.getInstance().getAppsFlyerUID(context) + Adapty.setIntegrationIdentifier("appsflyer_id", uid) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.updateAttribution(conversionData, "appsflyer") { error -> + if (error != null) { + // Handle the error + } + } } } ``` ### Branch Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırması](branch#connect-your-app-to-branch) bölümüne bakın. ```diff showLineNumbers // Login and update attribution Branch.getAutoInstance(this) .setIdentity("YOUR_USER_ID") { referringParams, error -> referringParams?.let { data -> - Adapty.updateAttribution(data, AdaptyAttributionSource.BRANCH) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.updateAttribution(data, "branch") { error -> + if (error != null) { + // Handle the error + } + } } } // Logout Branch.getAutoInstance(context).logout() ``` ### Facebook Ads Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Facebook Ads entegrasyonu için SDK yapılandırması](facebook-ads#connect-your-app-to-facebook-ads) bölümüne bakın. ```diff showLineNumbers - val builder = AdaptyProfileParameters.Builder() - .withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context)) - - Adapty.updateProfile(builder.build()) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier( + "facebook_anonymous_id", + AppEventsLogger.getAnonymousAppDeviceGUID(context) + ) { error -> + if (error != null) { + // Handle the error + } + } ``` ### Firebase ve Google Analytics \{#firebase-and-google-analytics\} Aşağıda gösterildiği gibi mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers // After Adapty.activate() FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId -> - Adapty.updateProfile( - AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build() - ) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error -> + if (error != null) { + // Handle the error + } + } } ``` ```diff showLineNumbers // After Adapty.activate() - FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build(); - - Adapty.updateProfile(params, error -> { - if (error != null) { - // Handle the error - } - }); - }); + FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> { + if (error != null) { + // Handle the error + } + }); + }); ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonuna yönelik SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın. ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withMixpanelUserId(mixpanelAPI.distinctId) - .build() - - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [OneSignal entegrasyonunda SDK yapılandırması](onesignal#sdk-configuration) bölümüne bakın. ```diff showLineNumbers // SubscriptionID val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver { override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) { - val params = AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.current.id) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error -> if (error != null) { // Handle the error } } } } ``` ```diff showLineNumbers // SubscriptionID IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.getCurrent().getId()) - .build(); - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> { if (error != null) { // Handle the error } }); }; ``` ```diff showLineNumbers // PlayerID val osSubscriptionObserver = OSSubscriptionObserver { stateChanges -> stateChanges?.to?.userId?.let { playerId -> - val params = AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error -> if (error != null) { // Handle the error } - } } } ``` ```diff showLineNumbers // PlayerID OSSubscriptionObserver osSubscriptionObserver = stateChanges -> { OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null; String playerId = to != null ? to.getUserId() : null; if (playerId != null) { - AdaptyProfileParameters params1 = new AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build(); - - Adapty.updateProfile(params1, error -> { + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> { if (error != null) { // Handle the error } - }); } }; ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırmasına](pushwoosh#sdk-configuration) bakın. ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().hwid) - .build() - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error -> if (error != null) { // Handle the error } } ``` ```diff showLineNumbers - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().getHwid()) - .build(); - - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> { if (error != null) { // Handle the error } }); ``` --- # File: migration-to-android-sdk-v3 --- --- title: "Adapty Android SDK'yı v3.0'a Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Android SDK v3.0'a geçin." --- Adapty SDK v3.0, yeni ve heyecan verici [Adapty Paywall Builder](adapty-paywall-builder)'ı destekler; bu, paywall oluşturmak için kullanılan kodsuz, kullanıcı dostu aracın yeni sürümüdür. Maksimum esneklik ve zengin tasarım özellikleriyle paywallleriniz çok daha etkili ve kârlı hale gelecek. Adapty SDK'ları bir BoM (Bill of Materials) olarak sunulur; bu sayede uygulamanızdaki Adapty SDK ve AdaptyUI SDK sürümleri tutarlı kalır. v3.0'a geçiş yapmak için kodunuzu aşağıdaki gibi güncelleyin: ```diff showLineNumbers dependencies { ... - implementation 'io.adapty:android-sdk:2.11.5' - implementation 'io.adapty:android-ui:2.11.3' + implementation platform('io.adapty:adapty-bom:3.0.4') + implementation 'io.adapty:android-sdk' + implementation 'io.adapty:android-ui' } ``` ```diff showLineNumbers dependencies { ... - implementation("io.adapty:android-sdk:2.11.5") - implementation("io.adapty:android-ui:2.11.3") + implementation(platform("io.adapty:adapty-bom:3.0.4")) + implementation("io.adapty:android-sdk") + implementation("io.adapty:android-ui") } ``` ```diff showLineNumbers //libs.versions.toml [versions] .. - adapty = "2.11.5" - adaptyUi = "2.11.3" + adaptyBom = "3.0.4" [libraries] .. - adapty = { group = "io.adapty", name = "android-sdk", version.ref = "adapty" } - adapty-ui = { group = "io.adapty", name = "android-ui", version.ref = "adaptyUi" } + adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } + adapty = { module = "io.adapty:android-sdk" } + adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... + implementation(libs.adapty.bom) implementation(libs.adapty) implementation(libs.adapty.ui) } ``` --- # End of Documentation _Generated on: 2026-07-24T13:02:34.238Z_ _Successfully processed: 41/41 files_