# FLUTTER - 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.289Z Total files: 44 --- # File: sdk-installation-flutter --- --- title: "Flutter SDK'yı Yükleyin ve Yapılandırın" description: "Flutter için Adapty SDK'yı abonelik tabanlı uygulamalara adım adım yükleme rehberi." --- Adapty SDK, Flutter 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**: [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız bu modüle ihtiyaç duyarsınız. Paywall Builder, platformlar arası paywall'lar oluşturmayı kolaylaştıran, kod gerektirmeyen kullanıcı dostu bir araçtır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywall gösterme, satın alma yapma ve diğer temel işlevleri kapsayan tam kurulumu içeren [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) göz atın. ::: ## Gereksinimler \{#requirements\} Adapty SDK, iOS 13.0+ sürümünü destekler; ancak paywall builder ile oluşturulan paywallların düzgün çalışması için iOS 15.0+ gereklidir. [Flow Builder](adapty-flow-builder) desteği ekleyen Adapty Flutter SDK 4.0, minimum gereksinimleri **iOS 15.0+**, **Xcode 26+** ve **Flutter 3.32.0+** (Dart 3.8.0+) olarak yükseltmektedir. Kurulum ayrıntıları için aşağıdaki [Adapty SDK 4.0](#adapty-sdk-40-swift-package-manager) bölümüne bakın. :::info Adapty, Google Play Billing Library 8.x sürümüne kadar uyumludur. Varsayılan olarak Adapty, Google Play Billing Library v7.0.0 ile çalışır; ancak daha yeni bir sürümü zorlamak istiyorsanız [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ükleme \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Flutter.svg?style=flat&logo=flutter)](https://github.com/adaptyteam/AdaptySDK-Flutter/releases) :::important Aşağıdaki adımlar en son kararlı SDK'yı (3.x) yükler. [Flow Builder](adapty-flow-builder) için gerekli olan ve [hızlı başlangıç](flutter-quickstart-paywalls) kılavuzunda kullanılan v4'e ihtiyacınız varsa, bunun yerine aşağıdaki [Adapty SDK 4.0: Swift Package Manager](#adapty-sdk-40-swift-package-manager) bölümünü izleyin. ::: 1. Adapty'yi `pubspec.yaml` dosyanıza ekleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: ^ ``` 2. Bağımlılıkları yüklemek için aşağıdaki komutu çalıştırın: ```bash showLineNumbers title="Terminal" flutter pub get ``` 3. Adapty SDK'larını uygulamanıza dahil edin: ```dart showLineNumbers title="main.dart" import 'package:adapty_flutter/adapty_flutter.dart'; ``` ### Adapty SDK 4.0: Swift Package Manager Adapty Flutter SDK 4.0'ı — [Flow Builder](adapty-flow-builder) desteği ekleyen — `pubspec.yaml` dosyanıza ekleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: 4.0.0 ``` v4 ile birlikte, yerel iOS SDK'sı artık CocoaPods üzerinden dağıtılmamaktadır — eklenti bunu yalnızca **Swift Package Manager** aracılığıyla çeker ([CocoaPods'un spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). Flutter 3.32–3.43 kullanıyorsanız, Swift Package Manager desteğini bir kez etkinleştirin: ```bash showLineNumbers title="Terminal" flutter config --enable-swift-package-manager ``` Flutter 3.44 ve sonraki sürümlerde Swift Package Manager varsayılan olarak etkin olduğundan herhangi bir işlem yapmanıza gerek yoktur. v4'teki API değişiklikleri için [taşıma kılavuzuna](migration-to-flutter-sdk-v4) bakın. ## Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK, 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. ```dart showLineNumbers title="main.dart" void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override void initState() { _initializeAdapty(); super.initState(); } Future _initializeAdapty() async { try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY'), ); } catch (e) { // handle the error } } Widget build(BuildContext context) { return Text("Hello"); } } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıralama için bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](flutter-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywalllar için hızlı başlangıç kılavuzuna](flutter-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ve [AdaptyUI modülünü yüklediyseniz](sdk-installation-flutter#install-adapty-sdk), AdaptyUI'ı da etkinleştirmeniz gerekir: :::note AdaptyUI ile ilgili bağımlılıklar, AdaptyUI etkinleştirilmiş olup olmadığından bağımsız olarak uygulamanıza bağlıdır. ::: :::important Kodunuzda, AdaptyUI'ı etkinleştirmeden önce önce çekirdek Adapty modülünü etkinleştirmeniz gerekir. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withActivateUI(true), // This automatically activates AdaptyUI ); ``` ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kayıt sistemini kurma \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri günlüğe kaydeder. Aşağıdaki seviyeler mevcuttur: | Seviye | Açıklama | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------- | | `AdaptyLogLevel.error` | Yalnızca hatalar loglanır. | | `AdaptyLogLevel.warn` | Kritik hatalara yol açmayan ancak dikkat edilmesi gereken hatalar ve SDK mesajları loglanır. | | `AdaptyLogLevel.info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır. Varsayılan değer. | | `AdaptyLogLevel.verbose` | Hata ayıklama sırasında işe yarayabilecek ek bilgiler (fonksiyon çağrıları, API sorguları vb.) loglanır. | | `AdaptyLogLevel.debug` | Hata ayıklama bilgileri loglanır. | Adapty'yi yapılandırmadan önce uygulamanızda log seviyesini ayarlayabilirsiniz: ```dart showLineNumbers title="main.dart" // Set log level before activation. // 'verbose' is recommended for development and the first production release await Adapty().setLogLevel(AdaptyLogLevel.verbose); // Or set it during configuration await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withLogLevel(AdaptyLogLevel.verbose), ); ``` ### Veri politikaları \{#data-policies\} Adapty, siz 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şımını 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. Bu parametreyi kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özellikler uygulamanız için gerekli olmadığında gereksiz veri toplamayı azaltmak amacıyla kullanabilirsiniz. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withIpAddressCollectionDisabled(true), ); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `appleIdfaCollectionDisabled` (iOS) veya `googleAdvertisingIdCollectionDisabled` (Android) parametresini `true` olarak ayarlayın. Varsayılan değer `false`'tur. App Store/Play Store politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak veya uygulamanız reklam kimliklerine dayalı attribution ya da analiz gerektirmiyorsa bu parametreyi kullanın. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleIdfaCollectionDisabled(true) // iOS ..withGoogleAdvertisingIdCollectionDisabled(true), // Android ); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlayın \{#set-up-media-cache-configuration-for-adaptyui\} Modül, Adapty SDK ile birlikte otomatik olarak etkinleştirilir. Paywall Builder kullanmıyorsanız ve AdaptyUI modülünü devre dışı bırakmak istiyorsanız, etkinleştirme sırasında `withActivateUI(false)` parametresini geçin. Varsayılan olarak, AdaptyUI performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) önbelleğe alır. Önbellek ayarlarını özel bir yapılandırma sağlayarak özelleştirebilirsiniz. Varsayılan önbellek sınırlarını geçersiz kılmak için `withMediaCacheConfiguration` kullanın. Bu isteğe bağlıdır; bu metodu çağırmazsanız varsayılan değerler kullanılır (100 MB disk boyutu, sınırsız bellek sayısı). Ancak yapılandırma nesnesini oluşturursanız tüm parametreleri zorunludur. ```dart showLineNumbers title="main.dart" final mediaCacheConfig = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit: 2147483647, // max int value diskStorageSizeLimit: 200 * 1024 * 1024, // 200 MB ); await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withMediaCacheConfiguration(mediaCacheConfig), ); ``` **Parametreler:** | Parametre | Varlık | Açıklama | |-------------------------|----------|-----------------------------------------------------------------------------| | memoryStorageTotalCostLimit | gerekli | Bellekteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer 100 MB'tır. | | memoryStorageCountLimit | gerekli | Bellek depolamasındaki öğe sayısı sınırı. Varsayılan değer maksimum int değeridir. | | diskStorageSizeLimit | gerekli | Diskteki dosya boyutu sınırı (bayt cinsinden). Varsayılan değer 100 MB'tır. | ### Yerel access level'ları etkinleştirme (Android) \{#enable-local-access-levels-android\} Varsayılan olarak, [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `withGoogleLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleLocalAccessLevelAllowed(true), ); ``` ### Yedekten geri yükleme sırasında verileri temizle \{#clear-data-on-backup-restore\} `appleClearDataOnBackup` değeri `true` olarak ayarlandığında, SDK uygulamanın iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywalllar dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla yeniden başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleClearDataOnBackup(true) // default – false ); ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Otomatik Yedekleme yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `` etiketinin tools içerdiğinden emin olun: ```xml ... ``` #### 2. `` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml ... ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla 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ümleriyle uyumluluk 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 çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" #### Android'de başka bir uygulamadan geri döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} 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ı şekilde yeniden oluşturabilir ya da yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına veya iptal edilmiş gibi işlenmesine yol açabilir. Satın almaların düzgün ç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 ve 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 ``` #### Podfile SWIFT_VERSION geçersiz kılmasından kaynaklanan Swift 6 derleme hataları \{#swift-6-build-errors-caused-by-podfile-swift-version-override\} Flutter uygulamanızı iOS için derlerken Adapty pod hedeflerinde Swift 6 derleme hataları görebilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içindeki `@Sendable` uyumsuzlukları, Adapty türlerinde eksik `Sendable` uyumluluğu veya aktör yalıtım hataları yer alır. Adapty pod'ları `s.swift_version = '6.0'` olarak tanımlar ve derleme için Swift 6 gerektirir. Kendi uygulama kodunuz Swift 5'te kalabilir — yalnızca Adapty pod hedefleri (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`, `AdaptyLogger`, `AdaptyPlugin`) Swift 6 ile derlenmelidir. En yaygın neden, `ios/Podfile` dosyasındaki her pod hedefi için `SWIFT_VERSION` değerini yeniden yazan bir `post_install` hook'udur: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **Düzeltme**: Adapty pod hedeflerini geçersiz kılma işleminin dışında bırakın: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` Ardından `ios/` dizininden `pod install` komutunu çalıştırın ve yeniden derleyin. Doğrulamak için `ios/Pods/Pods.xcodeproj` dosyasını açın, `Adapty` pod hedefini seçin → **Build Settings** → **Swift Language Version**. Değerin **Swift 6** olması gerekir. --- # File: flutter-quickstart-paywalls --- --- title: "Flutter SDK ile Flow Builder kullanarak satın almaları etkinleştirin" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmek için hızlı başlangıç kılavuzu." --- Uygulama içi satın almaları 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 ederseniz bunun yerine paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](flutter-quickstart-manual). - [**Placement'lar**](placements) – flow'ları uygulamanızda nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Flow'ları kontrol panelindeki placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu sayede A/B testi yürütmek ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın almaları etkinleştirmek için size üç yol sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder; karmaşık satın alma akışı, fiş doğrulama ve abonelik yönetimini arka planda halleder. | | Elle oluşturulan paywalllar | 🟡 Orta | Paywall arayüzünü uygulama kodunuzda kendiniz implement edersiniz, ancak ürün tekliflerinde esnekliği korumak için yine de Adapty'den flow nesnesini alırsınız. [Rehbere](flutter-quickstart-manual) bakın. | | Observer mode | 🔴 Zor | Zaten kendi satın alma altyapınız var ve bunu kullanmaya devam etmek istiyorsunuz. Observer mode'un Adapty'de bazı kısıtlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulmuş bir flow'un nasıl uygulanacağını göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, bkz. [Paywallları manuel olarak uygulama](flutter-quickstart-manual). ::: Adapty Flow Builder'da oluşturulmuş 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 ve satın almaları 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 butonlara tıkladığında bağlantı açın veya flow'u kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Uygulamanızı Adapty Kontrol Paneli'nde [App Store](initial_ios) ve/veya [Google Play](initial-android) ile bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ona ürün ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'u ekleyin](create-placement). 5. Uygulama kodunuza [Adapty SDK'yı yükleyip etkinleştirin](sdk-installation-flutter). Bu kılavuz Adapty Flutter SDK v4 API'larını kullanır. :::tip Bu adımları tamamlamanın en hızlı yolu, [hızlı başlangıç kılavuzunu](quickstart) takip etmek veya [Developer CLI](developer-cli-quickstart) kullanarak paywall'lar ve placement'lar oluşturmaktır. ::: ## 1. Flow'u alın \{#1-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şturulmuş 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 `hasViewConfiguration` özelliğini kontrol ederek bunun builder'da oluşturulup oluşturulmadığını doğrulayın. 2. `createFlowView` metodunu kullanarak flow view'ı oluşturun. View, 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 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. ::: ```dart showLineNumbers try { // the requested flow final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final view = await AdaptyUI().createFlowView( flow: flow, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## 2. Flow'u görüntüleme \{#display-the-flow\} Artık flow view'a sahip olduğunuzda, onu görüntülemek için birkaç satır kod eklemeniz yeterli. Flow'u görüntülemek için `createFlowView` metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez gösterilebilir: kapatıldıktan sonra view bellekten silinir. Flow'u tekrar görüntülemeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createFlowView` metodunu bir kez daha çağırın. ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Bir flow'un nasıl görüntüleneceğine dair daha fazla ayrıntı için [kılavuzumuza](flutter-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#handle-button-actions\} Kullanıcılar flow içindeki butonlara tıkladığında Flutter SDK, satın alma işlemlerini, restorasyon işlemlerini, görünümü kapatmayı ve URL açmayı otomatik olarak yönetir. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve kodunuzda bu eylemleri yönetmeniz gerekir. Flow ekranındaki süreçleri kontrol etmek veya izlemek için `AdaptyUIFlowsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın. Bir kullanıcı bir eylem gerçekleştirdiğinde `flowViewDidPerformAction` tetiklenir ve uygulamanızın eylem ID'sine göre yanıt vermesi gerekir. Üç observer yöntemi **zorunludur**: `flowViewDidFinishPurchase`, `flowViewDidFinishRestore` ve `flowViewDidReceiveError` — bunlar olmadan sınıfınız derlenmez. :::tip Buton [aksiyonlarını](flutter-handle-paywall-actions) ve [olayları](flutter-handling-events) nasıl yöneteceğinize dair kılavuzlarımızı okuyun. ::: Gözlemciyi, bir widget'a bağlamak yerine bağımsız ve uzun ömürlü bir nesne olarak uygulayın. Uygulama genelinde tek bir global gözlemci slotu paylaşıldığından, bunu bir `State`'e bağlamak ekranı sızdırır (SDK ona güçlü bir referans tutar) ve bir sonraki ekran kendini kaydettiğinde sessizce değiştirilir. `extends` kullanmak aynı zamanda SDK'nın varsayılan davranışını miras aldığından, üç zorunlu metodun yanı sıra yalnızca önem verdiğiniz callback'leri override etmeniz yeterlidir. ```dart showLineNumbers title="Flutter" // A dedicated, long-lived handler for flow events. // It does NOT live inside a Widget/State, so it never leaks and is never // silently replaced when screens are pushed or popped. class FlowEventsHandler extends AdaptyUIFlowsEventsObserver { // A single, app-wide instance — same idiom as Adapty() and AdaptyUI(). static final FlowEventsHandler _instance = FlowEventsHandler._(); factory FlowEventsHandler() => _instance; FlowEventsHandler._(); // This method is called when user performs an action on the flow UI. // Overriding it replaces the default behavior (dismiss on close, open URLs), // so keep those cases if you want to preserve it. @override void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): // close the flow on the Android back button view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } // Required: decide what happens after a purchase finishes @override void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { if (purchaseResult is! AdaptyPurchaseResultUserCancelled) { view.dismiss(); } } // Required: dismiss the flow once a restore succeeds @override void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { view.dismiss(); } // Required: handle rendering and other view errors @override void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { print('Flow error: $error'); view.dismiss(); } } ``` İşleyiciyi uygulama başlangıcında, herhangi bir flow gösterilmeden önce **bir kez** kaydedin: ```dart showLineNumbers title="Flutter" AdaptyUI().setFlowsEventsObserver(FlowEventsHandler()); ``` ## 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 alma işlemini tamamlayabildiğinizden emin olmak için satın almalarınızı [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da test edin. Şimdi, doğru kullanıcılara paywall gösterdiğinizden veya ücretli özelliklere erişim verdiğinizden emin olmak için [kullanıcıların access level'ını kontrol etmeniz](flutter-check-subscription-status) gerekiyor. ## Tam örnek \{#full-example\} Tüm bu adımların uygulamanızda birlikte nasıl entegre edileceğini aşağıda görebilirsiniz. ```dart void main() { // Register a single, long-lived observer once, before any flow is shown. // It is intentionally a plain object (NOT a Widget/State): its lifetime is the // whole app, so it never leaks and is never silently replaced when screens are // pushed or popped. AdaptyUI().setFlowsEventsObserver(FlowEventsHandler()); runApp(MaterialApp(home: FlowScreen())); } /// A dedicated handler for AdaptyUI flow events. /// /// It `extends` [AdaptyUIFlowsEventsObserver] (rather than being implemented /// by a `State`), which gives you two things for free: /// * the SDK's sensible defaults for optional callbacks, so besides the three /// required methods you only override what you actually care about; /// * a lifecycle that is independent of the widget tree — there is no strong /// reference back into a `Widget`, so nothing leaks and there is nothing to /// unregister. /// /// Every callback receives the [AdaptyUIFlowView] it relates to, so handling /// flow actions never requires a `BuildContext` or widget state. class FlowEventsHandler extends AdaptyUIFlowsEventsObserver { // A single, app-wide instance — same idiom as Adapty() and AdaptyUI(). static final FlowEventsHandler _instance = FlowEventsHandler._(); factory FlowEventsHandler() => _instance; FlowEventsHandler._(); // Called when the user performs an action on the flow UI. @override void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): // close the flow on the Android back button view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): // Open the URL natively, honoring the dashboard browser setting. AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } // Required: decide what happens after a purchase finishes. @override void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { if (purchaseResult is! AdaptyPurchaseResultUserCancelled) { view.dismiss(); } } // Required: dismiss the flow once a restore succeeds. @override void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { view.dismiss(); } // Required: handle rendering and other view errors. @override void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { print('Flow error: $error'); view.dismiss(); } } class FlowScreen extends StatefulWidget { const FlowScreen({super.key}); @override State createState() => _FlowScreenState(); } class _FlowScreenState extends State { @override void initState() { super.initState(); _showFlowIfNeeded(); } Future _showFlowIfNeeded() async { try { final flow = await Adapty().getFlow( placementId: 'YOUR_PLACEMENT_ID', ); if (!flow.hasViewConfiguration) return; final view = await AdaptyUI().createFlowView(flow: flow); await view.present(); } catch (_) { // Handle any errors (network, SDK issues, etc.) } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Adapty Flow Example')), body: Center( // Add a button to re-trigger the flow for testing purposes. child: ElevatedButton( onPressed: _showFlowIfNeeded, child: const Text('Show Flow'), ), ), ); } } ``` --- # File: flutter-check-subscription-status --- --- title: "Flutter SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Flutter uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir. Bu makalede, kullanıcılara paywall mı göstermeniz gerektiğini yoksa ücretli özelliklere erişim mi tanımanız gerektiğini belirlemek için profil durumuna nasıl erişeceğinizi öğreneceksiniz. ## Abonelik durumunu alma \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profilindeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verilerine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) veya güncellemeyi zorlamak istediğinizde `getProfile` çağırın. - Abonelik durumu her değiştiğinde otomatik olarak güncellenen yerel bir kopya tutmak için **otomatik profil güncellemeleri** ayarlayın. ### Profil alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek üzere `Adapty().didUpdateProfileStream.listen()` kullanın — kullanıcının abonelik durumu her değiştiğinde Adapty bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncel profil verilerini saklayın; böylece ek ağ isteği yapmadan uygulama genelinde kullanabilirsiniz. ```dart class SubscriptionManager { AdaptyProfile? _currentProfile; SubscriptionManager() { // Listen for profile updates Adapty().didUpdateProfileStream.listen((profile) { _currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() bool hasAccess() { return _currentProfile?.accessLevels['premium']?.isActive ?? false; } } ``` :::note Adapty, uygulamanız başladığında profil güncelleme akışı dinleyicisini otomatik olarak çağırır ve cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sağlar. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim tanıma konusunda anlık kararlar almanız gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girerken veya belirli içerikleri görüntülemeden önce gibi senaryolar için kullanışlıdır. ```dart Future _checkAccessLevel() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false; } catch (e) { print('Error checking access level: $e'); return false; // Show paywall if access check fails } } Future _initializePaywall() async { await _loadPaywall(); final hasAccess = await _checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların satın aldıklarına erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](flutter-quickstart-identify) öğrenin. --- # File: flutter-quickstart-identify --- --- title: "Flutter SDK'da kullanıcıları tanımlama" description: "Flutter'da uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa sizin içindir. Burada, Adapty'deki kullanıcı profilleriyle nasıl çalışacağınızı ve bunları mevcut kimlik doğrulama sisteminizle nasıl uyumlu hale getireceğinizi öğreneceksiniz. ::: Kullanıcıların satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız arka uç kimlik doğrulaması kullanmıyor ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanızda arka uç kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılar bölümüne](#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 çapraz referanslamak için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar şöyledir: | | 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ında satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profiller | Oturumlar ve cihazlar arasında aynı profil | | **Veri kalıcılığı** | Anonim kullanıcıların verileri uygulama kurulumuna bağlıdır | Tanımlanmış kullanıcıların verileri uygulama kurulumları arasında kalıcı olarak saklanır | ## Anonim kullanıcılar \{#anonymous-users\} Arka uç kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK, uygulamanın ilk başlatılması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 profilleriyle ve mağaza hesaplarıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **etkinleştirmede yeni bir anonim profil oluşturur**. 4. Kullanıcı daha önce uygulamanızda satın alma yaptıysa, varsayılan olarak satın almaları SDK etkinleştirildiğinde App Store'dan otomatik olarak senkronize edilir. Anonim kullanıcılarla her kurulumda yeni profiller oluşturulur; ancak bu bir sorun değildir çünkü Adapty analitiğinde [neyin yeni kurulum 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, bir cihazdaki her uygulama kurulumu (yeniden yüklemeler dahil) bir kurulum olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamadaki kullanıcıları tanımlamak için iki seçeneğiniz var: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğrulandıklarında customer user ID ile `identify()` çağrısı yapın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başlatıldığında zaten bir customer user ID saklıyorsanız, bunu `activate()` çağrısında gönderin. :::important Varsayılan olarak, Adapty 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. Ayrıntılar 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şlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kaydolduktan 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 profille ilişkilendirir. - 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ı kimlikleri 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 kabul edilir. ::: Diğer SDK metodlarını çağırmadan önce her zaman `identify` işlemini `await` ile bekleyin. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar veya anonim profile düşer. Bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Her kullanıcı için benzersiz } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### 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 bunu `activate` metodunda gönderebilirsiniz. Bir customer user ID bilseniz de bunu yalnızca etkinleştirmeden sonra ayarlarsanız, etkinleştirme sırasında Adapty yeni bir anonim profil oluşturacak ve yalnızca `identify` çağrısından sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane geçirebilirsiniz. Yeni bir tane geçirirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID ile ilişkilendirilir. :::note Varsayılan olarak, anonim profil oluşturmak analitik kontrol panellerini etkilemez çünkü kurulumlar cihaz kimliklerine göre sayılır. Bir cihaz kimliği, bir cihazdaki mağazadan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, bunun birinci mi yoksa tekrarlanan bir kurulum mu olduğuna, ya da mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturma (SDK etkinleştirmesinde veya oturum kapatmada), giriş yapma veya uygulamayı yeniden yüklemeden yükseltme ek kurulum olayları oluşturmaz. Kurulumları benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** sayfasına gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) seçeneğini yapılandırın. ::: ```dart showLineNumbers" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. ); } catch (e) { // handle the error } ``` ### Kullanıcıları oturumu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir düğmeniz varsa, `logout` metodunu kullanın. :::important Kullanıcıların oturumunu kapatmak, kullanıcı için yeni bir anonim profil oluşturur. ::: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::info Kullanıcıları uygulamaya tekrar giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın alma yapılmasına izin 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 korumalarını sağlamanız gerekir: 1. Oturum açmamış bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil kimliğiyle ilişkilendirir. 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 profille bağlantılıysa), profil geçişinden sonra gerçek access level'ı almanız gerekir. Tanımlamanın hemen ardından [`getProfile`](flutter-check-subscription-status) çağrısı yapabilir veya veriler otomatik olarak senkronize olsun diye [profil güncellemelerini dinleyebilirsiniz](flutter-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını başarıyla uyguladınız! Uygulama gelir elde etme sürecinizde başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboardinglar**](flutter-onboardings): Onboardinglarla kullanıcıları etkileyin ve elde tutmayı artırın - [**Entegrasyonlar**](configuration): Pazarlama attribution ve analitik hizmetleriyle tek satır kodla entegre edin - [**Özel profil özellikleri ayarlama**](flutter-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywalllar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-flutter --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Flutter uygulamanıza entegre edin" description: "Adapty SDK'sını Flutter uygulamanıza baştan sona entegre etmek için AI kodlama aracınızla adapty-sdk-integration becerisini 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 beceri beta aşamasındadır. Takılıp kalır veya beklenmedik şekilde davranırsa, AI aracınıza her aşamayı doğru belgelerle adım adım anlatan [adım adım entegrasyon kılavuzunu](adapty-cursor-flutter) izleyin. ::: [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-flutter --- --- title: "Adapty'yi Flutter uygulamanıza yapay zeka yardımıyla entegre etme" description: "Cursor, Context7, ChatGPT, Claude veya diğer yapay zeka araçlarını kullanarak Adapty'yi Flutter uygulamanıza adım adım entegre etme rehberi." --- Bu rehber, bir yapay zeka kodlama aracıyla Adapty'yi Flutter uygulamanıza adım adım entegre etme sürecini anlatır — doğru Adapty dokümanlarını doğru sırada 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 biraz kontrol paneli yapılandırması gerektirir. Bunu etkileşimli bir LLM becerisini kullanarak ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilir) \{#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 — her adım için Kontrol Paneli'ni açmadan — kurmasına olanak tanır. Yalnızca Kontrol Paneli'nde [mağazalarınızı bağlamanız](integrate-payments) gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra, ajanınızda `/adapty-cli` komutunu çalıştırın. Mağazalarınızı bağlamak için Kontrol Paneli'ni ne zaman açacağınız dahil her adımda sizi yönlendirecektir. ### Kontrol Paneli Yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, herhangi bir kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için arayamaz; bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Flutter uygulamanız her iki platformu da hedefliyorsa hem App Store hem de Google Play'i bağlayın. Bu, satın almaların çalışması için zorunludur. [Uygulama mağazalarını bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin ve **API keys** bölümünü bulun. Kodda bu, Adapty yapılandırmasına geçtiğiniz dizedir. 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 onları paywall'lar aracılığıyla iletir. [Ürün ekleyin](quickstart-products) 4. **Paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasında bir paywall oluşturun, ardından **Placements** sayfasında bunu bir placement'a atayın. Kodda, placement ID, `Adapty().getPaywall()` fonksiyonuna geçirdiğiniz string değerdir. [Paywall oluştur](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde, **Products** sayfasında her ürün için yapılandırın. Kodda, `profile.accessLevels['premium']?.isActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne bağlı olarak farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Beş bilgiye de sahip olduğunuzda kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'im Y" — böylece doğru başlatma ve paywall çekme kodunu üretebilir. ::: ### Hazır olduğunuzda ayarlayın \{#set-up-when-ready\} Kodlamaya başlamak için bunlar zorunlu değildir, ancak entegrasyonunuz olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliğine gerek yoktur. [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). ## LLM'nize Adapty Dokümanlarını Besleyin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi Kullanın (önerilir) [Context7](https://context7.com), LLM'inize güncel Adapty belgelerine doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, ne sorduğunuza göre doğru belgeleri otomatik olarak getirir — manuel URL yapıştırmaya gerek yok. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurulum için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, editörünüzü algılayarak Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırdıktan sonra, Adapty kütüphanesini prompt'larınızda referans alın: ``` Use the adaptyteam/adapty-docs library to look up how to install the Flutter SDK ``` :::warning Context7, belge 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ımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanlara erişin \{#use-plain-text-docs\} Her 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** düğmesine tıklayın. Örneğin: [adapty-cursor-flutter.md](https://adapty.io/docs/tr/adapty-cursor-flutter.md). Aşağıdaki [uygulama adım adım rehberi](#implementation-walkthrough)'nin her aşaması, yapıştırabileceğiniz `.md` bağlantılarıyla birlikte "Bunu LLM'nize gönderin" bloğu içerir. Aynı anda daha fazla doküman için aşağıdaki [dizin dosyalarına ve platforma özgü alt kümelere](#plain-text-doc-index-files) bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, Adapty entegrasyonunu uygulama sırasına göre ele alır. Her aşamada LLM'inize göndereceğiniz belgeler, tamamlandığında ne görmeniz gerektiği ve sık karşılaşılan sorunlar açıklanmaktadır. ### Entegrasyonunuzu Planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inize projenizi analiz etmesini ve bir uygulama planı oluşturmasını söyleyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), bunu kullanın; böylece LLM herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilir. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, takip etmesi gereken kılavuzları etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin no-code editöründe paywall'lar oluşturursunuz; SDK bunları otomatik olarak render eder. - [**Manuel oluşturulan paywall'lar**](flutter-making-purchases): Kendi paywall arayüzünüzü kod ile oluşturursunuz, ancak ürünleri çekmek ve satın almaları yönetmek için yine Adapty'yi kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korursunuz ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Quickstart'taki karşılaştırma tablosuna](flutter-quickstart-paywalls) göz atın. ### SDK'yı Yükleyin ve Yapılandırın \{#install-and-configure-the-sdk\} `flutter pub add` komutunu kullanarak Adapty SDK bağımlılığını ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temel adımdır — geri kalan her şey buna bağlıdır. **Kılavuz:** [Adapty SDK'yı Yükleyin ve Yapılandırın](sdk-installation-flutter) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-flutter.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Uygulama hem iOS hem Android'de derlenir ve çalışır. Hata ayıklama konsolu Adapty aktivasyon logunu gösterir. - **Dikkat:** "Public API key is missing" → yer tutucuyu **App settings** bölümündeki gerçek anahtarınızla değiştirdiğinizi kontrol edin. ::: ### Paywall'ları göster ve satın almaları yönet \{#show-paywalls-and-handle-purchases\} Placement ID'ye göre bir paywall getir, görüntüle ve satın alma olaylarını yönet. İhtiyacınız olan kılavuzlar, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerledikçe sandbox'ta test et — sona kadar bekleme. Kurulum talimatları için [Sandbox'ta satın almaları test et](test-purchases-in-sandbox) bölümüne bakın. **Kılavuzlar:** - [Paywall'lar ile satın almaları etkinleştirme (hızlı başlangıç)](flutter-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını alma](flutter-get-pb-paywalls) - [Paywall'ları gösterme](flutter-present-paywalls) - [Paywall olaylarını işleme](flutter-handling-events) - [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) Bu, çevrilecek herhangi bir MDX dokümantasyon içeriği içermiyor — yalnızca bir LLM'e gönderilmesi amaçlanmış bir kod bloğu var. Çevrilecek bir MDX dosyası gönderirseniz memnuniyetle çeviririm. :::tip[Checkpoint] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu 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. ::: **Kılavuzlar:** - [Özel paywallınızda satın almaları etkinleştirin (hızlı başlangıç)](flutter-quickstart-manual) - [Paywallları ve ürünleri getirin](fetch-paywalls-and-products-flutter) - [Remote config ile tasarlanmış paywall'ı gösterin](present-remote-config-paywalls-flutter) - [Satın alma yapın](flutter-making-purchases) - [Satın almaları geri yükleyin](flutter-restore-purchase) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-flutter.md - https://adapty.io/docs/tr/present-remote-config-paywalls-flutter.md - https://adapty.io/docs/tr/flutter-making-purchases.md - https://adapty.io/docs/tr/flutter-restore-purchase.md ``` :::tip[Checkpoint] - **Beklenen:** Özel paywall'ınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma diyaloğunu tetikliyor. - **Sorun yaşıyorsanız:** Ürün dizisi boş → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitleye sahip olduğunu doğrulayın. ::: **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode-flutter) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode-flutter) Bunu 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-flutter.md - https://adapty.io/docs/tr/report-transactions-observer-mode-flutter.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak yapılan bir sandbox satın alımından sonra, işlem Adapty kontrol panelindeki **Event Feed** bölümünde görünür. - **Dikkat:** Hiç event yoksa → işlemleri Adapty'e raporladığınızı ve sunucu bildirimlerinin her iki mağaza için yapılandırıldığını doğrulayın. ::: ### Abonelik durumunu kontrol etme \{#check-subscription-status\} Satın alımın ardından, premium içeriğe erişimi kısıtlamak için kullanıcı profilindeki aktif access level'ı kontrol edin. **Kılavuz:** [Abonelik durumunu kontrol etme](flutter-check-subscription-status) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın alımının ardından `profile.accessLevels['premium']?.isActive` değeri `true` döner. - **Dikkat:** Satın alımdan sonra `accessLevels` boş geliyor → ürüne kontrol panelinde bir access level atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Uygulama kullanıcı hesaplarını Adapty profillerine bağlayarak satın alımların cihazlar arasında kalıcı olmasını sağlayın. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](flutter-quickstart-identify) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-quickstart-identify.md ``` :::tip[Checkpoint] - **Beklenen:** `Adapty().identify()` çağrısından sonra, kontrol panelindeki **Profiles** bölümünde özel kullanıcı kimliğiniz görünür. - **Dikkat:** Anonim profil attribution sorunlarından kaçınmak için `identify` fonksiyonunu aktivasyondan sonra, paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlanma \{#prepare-for-release\} Entegrasyonunuz sandbox ortamında çalışır hale geldikten sonra, her şeyin production'a hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Rehber:** [Yayın kontrol listesi](release-checklist) Bunu LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Checkpoint] - **Beklenen:** Tüm kontrol listesi maddeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Sunucu bildirimleri eksikse → **App settings → iOS SDK** bölümünden App Store Server Notifications'ı ve **App settings → Android SDK** bölümünden Google Play Real-Time Developer Notifications'ı yapılandırın. ::: ## Düz metin belge indeks dosyaları \{#plain-text-doc-index-files\} LLM'nize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty belgelerini listeleyen veya bir araya getiren indeks dosyaları sunuyoruz: - [`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ı yapay zeka ajanlarının (örneğin ChatGPT) `llms.txt` dosyasını indirip sohbete yüklemeniz gerekebileceğini unutmayın. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hâlde. Çok büyük — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Flutter'a özel [`flutter-llms.txt`](https://adapty.io/docs/tr/flutter-llms.txt) ve [`flutter-llms-full.txt`](https://adapty.io/docs/tr/flutter-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: flutter-get-pb-paywalls --- --- title: "Flow'ları ve paywall'ları getir - Flutter" description: "Flutter uygulamanızda Adapty'den flow'ları ve paywall'ları çekin." --- [Flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda gösterebilirsiniz. İ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. Bu konunun flow'lar ve Paywall Builder ile özelleştirilmiş paywalllar için geçerli olduğunu 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-flutter) 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 flow ve 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 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-flutter)'yı yükleyin.
## Flow/paywall getir \{#fetch-flowpaywall\} Flow Builder veya Paywall Builder ile bir flow veya paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir flow veya paywall, içinde neyin ve nasıl gösterileceğini zaten içerir. Yine de placement aracılığıyla ID'sini, görünüm konfigürasyonunu almanız ve ardından mobil uygulamanızda sunmanız gerekir. Flow veya paywall'ı mümkün olduğunca erken — ideally sunarken değil, çok daha önce — çekin ve [görünümünü](flutter-get-pb-paywalls#fetch-the-view-configuration) oluşturun. `createFlowView` metodu görünüm yapılandırmasını yükler ve arka planda görselleri indirip önbelleğe almaya başlar. Bu metodu ne kadar erken çağırırsanız, indirmelerin tamamlanması için o kadar fazla zaman olur. Flow veya paywall'ı sunduğunuzda, yapılandırma ve görseller zaten önbellekte hazır olabilir. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // istenen flow/paywall } on AdaptyError catch (adaptyError) { // hatayı işle } catch (e) { // hatayı işle } ``` Parametreler: | Parametre | Varlık | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, 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 veriye erişmesini 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, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirebilirsiniz. Bu senaryoda kullanıcılar en son veriye ulaşamayabilir; 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üresince ağ isteklerini azaltmak için güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını 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, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda dahi güvenilirliği korurken her zaman paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.

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

Bu metodun zaman aşımını sınırlayan bir `Duration` değeri. 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`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.

| ## Yanıt parametreleri \{#response-parameters\} | Parametre | Açıklama | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Flow'un tanımlayıcılarını (`instanceIdentity`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve remote config'leri (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## View konfigürasyonunu getirme \{#fetch-the-view-configuration\} :::important Builder'da **Show on device** geçiş düğmesini etkinleştirdiğinizden emin olun. Bu seçenek açık değilse, view konfigürasyonu getirilemez. ::: Eğer placement **Flow Builder** veya **Paywall Builder** ile tasarlandıysa, Adapty kullanıcı arayüzünü sizin için oluşturur — alınan flow'un `hasViewConfiguration` özelliği `true` olur. `createFlowView` ile görünümü oluşturun, ardından [flow veya paywall'ı gösterin](flutter-present-paywalls). Eğer placement, Builder arayüzü olmayan özel bir paywall ise (`hasViewConfiguration` değeri `false`), bunun yerine [remote config paywall olarak ele alın](present-remote-config-paywalls-flutter). :::warning `createFlowView` metodunun sonucu yalnızca bir kez sunulabilir. Tekrar sunmanız gerekiyorsa `createFlowView` metodunu yeniden çağırın. ::: ```dart showLineNumbers try { final view = await AdaptyUI().createFlowView(flow: flow); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | zorunlu | İstenen flow/paywall için bir görünüm elde etmek üzere kullanılan `AdaptyFlow` nesnesi. | | **customTags** | opsiyonel | Özel etiketlerin ve çözümlenmiş değerlerinin bir haritasını tanımlar. Özel etiketler içerikte yer tutucu işlevi görerek flow/paywall içindeki kişiselleştirilmiş içerik için belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için [Paywall Builder'da özel etiketler](custom-tags-in-paywall-builder) konusuna bakın. | | **preloadProducts** | opsiyonel | Ekranda ürünlerin gösterilme zamanlamasını optimize etmek için etkinleştirin. `true` olduğunda AdaptyUI gerekli ürünleri otomatik olarak getirir. Varsayılan: `false`. | | **loadTimeout** | opsiyonel | Görünüm yapılandırmasının yüklenme süresini sınırlayan bir `Duration`. Zaman aşımına ulaşıldığında önbelleğe alınmış veriler veya yerel yedek kullanılır. | :::note Birden fazla dil kullanıyorsanız, [flow yerelleştirmesi eklemeyi](add-paywall-locale-in-adapty-paywall-builder) ve yerel ayar kodlarını doğru kullanmayı [buradan](flutter-localizations-and-locale-codes) öğrenin. ::: Görünümü elde ettikten sonra, [flow/paywall'ı gösterin](flutter-present-paywalls). ## Varsayılan kitle için bir flow veya paywall alın, daha hızlı getirmek için \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar 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 placement'a sahip olduğunuz ve kullanıcılarınızın zayıf bir internet bağlantısı bulunduğu durumlarda, bir flow veya paywall getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklandığı üzere, `getFlow` metoduyla flow veya paywall getirmek olduğunu anlamak kritik önem taşır. :::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ı paywall'lar göstermeniz gerekiyorsa, bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız gerekecek ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywall'larla karşılaşabileceğini kabul etmek durumunda kalacaksınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre) kaybetmeniz anlamına gelir. Bu dezavantajları kabul etmeye hazırsanız ve daha hızlı flow veya paywall yüklemenin avantajlarından yararlanmak istiyorsanız, `getFlowForDefaultAudience` yöntemini aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` yöntemini kullanmaya devam edin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow/paywall } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` | 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. Bu seçeneği öneriyoruz çünkü kullanıcılarınızın her zaman en güncel verilere ulaşmasını 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 senaryoda kullanıcılar her zaman en son 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 ağ isteklerini azaltmak amacıyla oturum boyunca kullanmak güvenlidir.

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

| ## Öğeleri özelleştir \{#customize-assets\} Flow/paywall'ınızdaki görsel ve videoları özelleştirmek için özel öğeleri uygulayın. Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir öğe paketinde, bu öğeleri ID'leri üzerinden hedefleyerek 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österme. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterme. - Video başlamadan önce bir önizleme görseli gösterme. Here's an example of how you can provide custom assets via a simple dictionary: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createFlowView( flow: flow, customAssets: customAssets, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir varlık bulunamazsa, flow/paywall varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `createFlowView` metoduna bir `customTimers` map'i geçirin. Her map anahtarı bir zamanlayıcı ID'si, değeri ise zamanlayıcının ne zaman sona ereceğini tanımlayan bir `DateTime` nesnesidir. İşte bir örnek: ```dart showLineNumbers try { final view = await AdaptyUI().createFlowView( flow: flow, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2027, 1, 1), // New Year 2027 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `customTimers` haritası, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Zamanlayıcının bitiş zamanına (örneğin Yılbaşı Günü) kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının flow'u açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman.
[Adapty Kontrol Paneli'nde yeni Paywall Builder ile paywall'ınızın görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda görüntüleyebilirsiniz. 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, Flutter SDK 3.3.0 veya daha yüksek sürümlerle çalışır. ::: Lütfen bu konunun Paywall Builder ile özelleştirilmiş paywall'lara atıfta bulunduğunu unutmayın. Paywall'larınızı manuel olarak uyguluyorsanız, [Mobil uygulamanızda remote config paywall'ları için paywall ve ürünleri getirin](fetch-paywalls-and-products-flutter) 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 paywall'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 paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-flutter)'yı kurun.
## 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 render etme konusunda endişelenmenize gerek yok. Bu tür bir paywall, paywall içinde ne gösterileceğini ve nasıl gösterileceğini içerir. Bununla birlikte, placement aracılığıyla kimliğini, görünüm konfigürasyonunu almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, paywall'ı ve [görünüm konfigürasyonunu](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız kritik önem taşır; böylece görseller kullanıcıya sunulmadan önce indirmek için yeterli süre kalır. Bir paywall almak için `getPaywall` metodunu kullanın: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir 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 parametrenin eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İ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ı gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-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 önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verileri 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 uğraştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda, kullanıcılar en son veriyi alamayabilir; ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında güvenle kullanılabilir.

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

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

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

Bu değer, bu metot için zaman aşımını sınırlar. Zaman aşımına ulaşılırsa, önbellekteki veri veya yerel yedek döndürülür.

Nadir durumlarda 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) veya `TimeInterval.seconds(5)` kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün kimliklerinin listesini, paywall tanımlayıcısını, remote config'i ve birçok diğer özelliği içeren bir [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | ## Paywall Builder ile tasarlanan paywall'ın görünüm konfigürasyonunu 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 konfigürasyonu alınamaz. ::: Paywall'ı aldıktan sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywall'ın nasıl gösterileceği konusunda size rehberlik edecektir. `ViewConfiguration` mevcutsa, bunu bir Paywall Builder paywall'ı olarak değerlendirin; değilse, [remote config paywall olarak ele alın](present-remote-config-paywalls-flutter). ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Görünümü aldıktan sonra [paywall'ı sunun](flutter-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 paywall'lar neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywall'ınız varsa ve kullanıcılarınızın zayıf bir internet bağlantısı varsa, bir paywall'ı getirmek 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 **All Users** kitlesi için paywall'ı getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Paywall Bilgisini Getirme](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklandığı gibi `getPaywall` metoduyla paywall'ı getirmek olduğunu anlamak çok önemlidir. :::warning `getPaywall` kullanmanızı neden ö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 gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız gerekecek ya da mevcut (eski) sürüme sahip kullanıcıların render edilmeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedeflemenin kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecek; bu, kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, aşağıdaki şekilde `getPaywallForDefaultAudience` metodunu kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall`'a bağlı kalın. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` metodu Flutter SDK 3.2.0 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, 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 parametrenin eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İ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ı gerektiği 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 önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verileri 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 uğraştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda, kullanıcılar en son veriyi alamayabilir; ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla 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 önceden tanımlanmış kimliklere sahiptir: `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 ayarlamanız](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 çalıştırmadan önce önizleme görseli gösterin. :::important Bu özelliği kullanmak için Adapty Flutter SDK'yı 3.8.0 veya daha yüksek bir sürüme güncelleyin. ::: İşte basit bir sözlük aracılığıyla özel varlıkları nasıl sağlayabileceğinize dair bir örnek: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets: customAssets, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir varlık bulunamazsa, paywall varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `createPaywallView` metoduna bir `customTimers` haritası geçirin. Haritadaki her anahtar bir zamanlayıcı ID'sidir ve değeri zamanlayıcının ne zaman sona ereceğini tanımlayan bir `DateTime` nesnesidir. İşte bir örnek: ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2025, 1, 1), // New Year 2025 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `customTimers` haritası, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Yeni Yıl Günü gibi zamanlayıcının bitiş anına kadar kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının paywall'ı açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman.
--- # File: flutter-present-paywalls --- --- title: "Flow ve paywallları görüntüleme - Flutter" description: "Adapty'nin monetizasyon özelliklerini kullanarak Flutter uygulamalarında flow ve paywallları gösterin." --- Flow Builder veya Paywall Builder kullanarak bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir flow veya paywall, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz, flow'lar ve Paywall Builder paywall'ları içindir. **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanmış paywall'ı render etme](present-remote-config-paywalls-flutter). ::: Adapty Flutter SDK, flow'ları ve paywall'ları sunmak için iki yol sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak göster \{#present-as-standalone-screen\} Bir flow veya paywall'ı bağımsız bir ekran olarak göstermek için, [`createFlowView`](flutter-get-pb-paywalls#fetch-the-view-configuration) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez gösterilebilir: kapatıldıktan sonra `view` bellekten serbest bırakılır. Flow veya paywall'ı tekrar göstermeniz gerekirse, yeni bir `view` örneği oluşturmak için `createFlowView` metodunu bir kez daha çağırın. ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::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 veya paywall'ı kapat \{#dismiss-the-flow-or-paywall\} Flow veya paywall'ı programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir view kapatıldığında bellekten silinir — kapatılmış bir view artık yeniden gösterilemez. Bunun yerine `createFlowView` ile yeni bir tane oluşturun. ::: ### Diyalog göster \{#show-dialog\} Android'de bir flow veya paywall görünümü gösterildiğinde, native uyarı diyalogları yerine bu metodu kullanın. Android'de normal uyarılar görünümün arkasında kalır ve kullanıcılar tarafından görülemez. Bu metod, diyaloğun tüm platformlarda flow veya paywall'ın üzerinde düzgün şekilde gösterilmesini sağlar. ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek flow veya paywall'ın iOS'ta nasıl sunulacağını yapılandırın. Bu parametre `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine gömme \{#embed-in-widget-hierarchy\} Mevcut widget ağacınıza bir flow veya paywall gömmek için `AdaptyUIFlowPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIFlowPlatformView( flow: flow, // The flow object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidReceiveError: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android platform view'ın çalışması için `MainActivity`'nizin `FlutterFragmentActivity`'yi genişlettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz yalnızca SDK v3.2.0 veya sonrasını gerektiren **yeni Paywall Builder paywall'ları** içindir. Paywall'ları sunma süreci, farklı Paywall Builder sürümleriyle tasarlanan paywall'lar ve remote config paywall'lar için farklılık gösterir. - **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls-flutter). ::: Adapty Flutter SDK, paywall'ları sunmak için iki yöntem sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak sunma \{#present-as-standalone-screen\} Bir paywall'ı bağımsız ekran olarak görüntülemek için, [`createPaywallView`](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar göstermeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createPaywallView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::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'ı kapatma \{#dismiss-the-paywall\} Paywall'ı programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Diyalog gösterme \{#show-dialog\} Android'de bir paywall görünümü sunulduğunda, yerel uyarı diyalogları yerine bu metodu kullanın. Android'de normal uyarılar paywall görünümünün arkasında kalır ve kullanıcılar tarafından görülemez. Bu metod, tüm platformlarda diyaloğun paywall'ın üzerinde düzgün şekilde gösterilmesini sağlar. ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek paywallın iOS'ta nasıl sunulacağını yapılandırın. Parametre, `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine gömme \{#embed-in-widget-hierarchy\} Bir paywall'ı mevcut widget ağacınıza gömmek için `AdaptyUIPaywallPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIPaywallPlatformView( paywall: paywall, // The paywall object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidFailRendering: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android platform view'un çalışması için `MainActivity` sınıfınızın `FlutterFragmentActivity`'yi extend ettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: --- # File: flutter-handle-paywall-actions --- --- title: "Flutter SDK'da buton eylemlerine yanıt verme" description: "Adapty kullanarak Flutter'da paywall buton eylemlerini daha iyi uygulama monetizasyonu için yönetin." --- Adapty builder kullanarak flow veya paywall oluşturuyorsanız, butonları doğru şekilde ayarlamak çok önemlidir: 1. [Builder'da bir buton ekleyin](paywall-buttons) ve ona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Uygulamanızda atadığınız her eylemi işlemek için kod yazın. Bu kılavuz, kodunuzda özel ve mevcut eylemlerin nasıl işleneceğini göstermektedir. :::warning **Görünümü kapatma ve URL'leri açma işlemleri**, varsayılan `flowViewDidPerformAction` uygulaması tarafından **otomatik olarak gerçekleştirilir** ve SDK'nın kendisi satın alma ile geri yükleme işlemlerini yönetir. Giriş yapma veya başka bir flow açma gibi diğer tüm buton eylemleri, uygulama kodunda uygun yanıtların yazılmasını gerektirir. *Tamamlanan* satın alma ve geri yükleme işlemlerine yanıt verme ise zorunlu gözlemci callback'lerinde gerçekleşir — bkz. [Flow & paywall olaylarını yönetme](flutter-handling-events). ::: ## Flow ve paywallları kapatma \{#close-flows-and-paywalls\} Flow veya paywallınıza kapatma düğmesi eklemek için builder'da bir düğme ekleyin ve bu düğmeye **Close** aksiyonunu atayın. Herhangi bir kod yazmanıza gerek yok: varsayılan `flowViewDidPerformAction` implementasyonu, `CloseAction` aldığında görünümü otomatik olarak kapatır. :::info Android sistem **Back** düğmesi artık görünümü varsayılan olarak kapatmıyor. Bu düğme, `flowViewDidPerformAction`'a `AndroidSystemBackAction` olarak iletilir; back düğmesinin flow veya paywallı kapatmasını istiyorsanız bunu kendiniz ele almanız gerekir. ::: Özel bir davranışa ihtiyaç duyuyorsanız `flowViewDidPerformAction` metodunu override edin — örneğin, v3'te olduğu gibi Android sistem geri tuşunda da görünümü kapatmak için: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } ``` :::warning `flowViewDidPerformAction` metodunu override etmek, varsayılan implementasyonun tamamının yerini alır — varsayılan kapatma ve URL açma davranışını korumak istiyorsanız `CloseAction` ve `OpenUrlAction` case'lerini eklemeyi unutmayın. ::: ## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (ör. 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. ::: Bir bağlantı açan düğme eklemek için (ör. **Terms of use** veya **Privacy policy**), builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. Varsayılan `flowViewDidPerformAction` implementasyonu URL'yi `AdaptyUI().openUrl` aracılığıyla yerel olarak açar; kontrol panelindeki uygulama içi veya harici tarayıcı ayarını dikkate alır. Bu nedenle herhangi bir kod yazmanız gerekmez. Varsayılan davranış çoğu durum için yeterlidir. URL'leri kendiniz açmak istiyorsanız handler'ı geçersiz kılın: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL in whatever way fits your app break; default: break; } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Builder'da bir buton ekleyin ve **Login** aksiyonunu atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` aksiyonu için bir işleyici uygulayın. ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Navigate to your login screen in whatever way fits your app break; default: break; } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yöneten bir buton eklemek için: 1. Builder'da bir buton 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, başka bir abonelik teklifleri veya tek seferlik satın alma seçenekleri setiniz varsa, başka bir flow veya paywall görüntüleyecek bir buton ekleyebilirsiniz: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Display another flow or paywall break; default: break; } } ``` Adapty paywall builder kullanarak paywall oluşturuyorsanız, butonları doğru şekilde ayarlamak çok önemlidir: 1. [Paywall builder'a bir buton ekleyin](paywall-buttons) ve bu butona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Uygulamanızda, atadığınız her eylemi işleyecek kodu yazın. Bu rehber, kodunuzda özel ve mevcut aksiyonları nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar ve yenilemeler otomatik olarak işlenir.** Paywall'ları kapatma veya bağlantı açma gibi diğer tüm buton aksiyonları, uygulama kodunda uygun yanıtların uygulanmasını gerektirir. ::: ## Paywall'ları kapatma \{#close-paywalls\} Paywall'ınızı kapatacak bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda `CloseAction` ve `AndroidSystemBackAction` eylemleri için bir handler uygulayın. :::info Flutter SDK'da `CloseAction` ve `AndroidSystemBackAction` eylemleri varsayılan olarak paywall'ı 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. ::: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; default: break; } } ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup link eklemek istiyorsanız (ör. kullanım koşulları ve satın alma restorasyon), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemine sahip butonlarla aynı şekilde yönetin. ::: Paywall'ınızdan link açan bir buton eklemek için (ör. **Kullanım Koşulları** veya **Gizlilik Politikası**): 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 bir tarayıcıda açan `openUrl` eylemi için bir handler uygulayın. ```dart // You have to install url_launcher plugin in order to handle urls: // https://pub.dev/packages/url_launcher void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case OpenUrlAction(url: final url): final Uri uri = Uri.parse(url); launchUrl(uri, mode: LaunchMode.inAppBrowserView); break; default: break; } } ``` ## 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 ona **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcıyı tanımlayan `login` eylemi için bir işleyici uygulayın. ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Navigate to your login screen in whatever way fits your app break; default: break; } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer eylemleri yönetecek bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin, **Custom** eylemini atayın ve bir ID belirleyin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir handler uygulayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa, başka bir paywall görüntüleyen bir buton ekleyebilirsiniz: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Başka bir paywall göster break; default: break; } } ``` --- # File: flutter-handling-events --- --- title: "Flutter - Flow ve paywall etkinliklerini yönetme" description: "Kullanıcı etkileşimlerini etkin şekilde izlemek için Adapty ile Flutter'da abonelikle ilgili olayları nasıl yöneteceğinizi keşfedin." --- :::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve render etme olaylarını kapsar. Görünümü kapatma ve bağlantı açma işlemleri, varsayılan `flowViewDidPerformAction` uygulaması tarafından yönetilir — bunları geçersiz kılmak veya özel buton eylemlerini işlemek için [buton eylemlerini yönetme kılavuzumuza](flutter-handle-paywall-actions) bakın. ::: Flow ve Paywall Builder ile oluşturulan paywall'lar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamaları (kapatma düğmeleri, URL'ler, ürün seçimleri vb.) ve flow veya paywall üzerinde gerçekleştirilen satın alma işlemlerine ilişkin bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızdaki flow veya paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIFlowsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setFlowsEventsObserver(this); ``` Üç observer metodu **zorunludur** — sınıfınız bunlar olmadan derlenmez: `flowViewDidFinishPurchase`, `flowViewDidFinishRestore` ve `flowViewDidReceiveError`. Diğer tüm metodlar isteğe bağlıdır. Daha önce ayarlanmış bir observer'ı kaldırmak için `setFlowsEventsObserver`'a `null` 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. ::: Aşağıdaki olay örnekleri, her nesne üzerinde mevcut olan özellikleri ve yorumlarda örnek değerleri göstermektedir. ### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\} #### Görünüm belirdi \{#view-appeared\} Bu metot, flow veya paywall görünümü ekranda gösterildiğinde çağrılır. :::note iOS'ta, kullanıcı bir paywall içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve bir web paywall uygulama içi tarayıcıda açıldığında da çağrılır. ::: ```dart showLineNumbers title="Flutter" void flowViewDidAppear(AdaptyUIFlowView view) { } ``` #### Görünüm kayboldu \{#view-disappeared\} Bu metot, flow veya paywall görünümü ekrandan kaldırıldığında çağrılır. :::note iOS'ta ayrıca, bir paywall'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button)'ı uygulama içi tarayıcıda kapandığında da tetiklenir. ::: ```dart showLineNumbers title="Flutter" void flowViewDidDisappear(AdaptyUIFlowView view) { } ``` #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı ya da sistem tarafından), bu metot çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) { // productId is a String: productId; // 'premium_monthly' } ```
#### 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: ```dart showLineNumbers title="Flutter" void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) { } ```
Etkinlik örneği (Genişletmek için tıklayın) ```dart void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' product.localizedTitle; // 'Premium Monthly' product.localizedDescription; // 'Premium subscription for 1 month' product.price.amount; // 9.99 (double) product.price.currencyCode; // 'USD' product.price.localizedString; // '$9.99' } ```
#### Tamamlanan satın alma \{#finished-purchase\} Bu yöntem **zorunludur**. Bir satın alma başarıyla tamamlandığında, kullanıcı satın almayı iptal ettiğinde veya satın alma işlemi beklemede göründüğünde çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ```
Olay örnekleri (Genişletmek için tıklayın) ```dart void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) break; case AdaptyPurchaseResultPending(): // no additional data break; case AdaptyPurchaseResultUserCancelled(): // no additional data break; } } ```
:::info v3'ten farklı olarak, bu metodun varsayılan bir davranışı yoktur — başarılı bir satın alma sonrasında görünüm artık otomatik olarak kapatılmaz. Bundan sonra ne olacağına siz karar verin: flow'a devam edin veya `view.dismiss()` çağrısı yapın. Bir ekranı kapatma hakkında ayrıntılar için [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) bölümüne bakın. ::: #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu metod, belirli bir ürün için bir [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şimleri dahildir: ```dart showLineNumbers title="Flutter" void flowViewDidFinishWebPaymentNavigation(AdaptyUIFlowView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **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`. | #### Başarısız satın alma \{#failed-purchase\} Bu yöntem, bir satın alma başarısız olduğunda (örneğin, ödeme sorunları veya ağ hataları nedeniyle) çağrılır. Kullanıcının başlattığı iptaller veya bekleyen işlemler için **tetiklenmez** — bunlar `flowViewDidFinishPurchase` tarafından ele alınır: ```dart showLineNumbers title="Flutter" void flowViewDidFailPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyError error) { } ``` #### Geri yükleme başlatıldı \{#started-restore\} Bir kullanıcı geri yükleme işlemini başlatırsa bu yöntem çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidStartRestore(AdaptyUIFlowView view) { } ``` #### Başarılı geri yükleme \{#successful-restore\} Bu metod **zorunludur**. Bir satın alma geri yükleme işlemi başarılı olursa çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { } ```
Etkinlik örneği (Genişletmek için tıklayın) ```dart void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) profile.subscriptions['premium_monthly']?.isActive; // true profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) } ```
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](flutter-listen-subscription-changes) konusuna, ekranı nasıl kapatacağınızı öğrenmek için ise [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} Bir satın alma geri yüklemesi başarısız olursa şu metod çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFailRestore(AdaptyUIFlowView view, AdaptyError error) { } ``` ### Veri çekme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürün dizisini geçmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir: ```dart showLineNumbers title="Flutter" void flowViewDidFailLoadingProducts(AdaptyUIFlowView view, AdaptyError error) { } ``` #### Görünüm hataları \{#view-errors\} Bu yöntem **zorunludur**. v3'teki `paywallViewDidFailRendering` yönteminin yerini alır: arayüz oluşturma sırasında meydana gelen hatalar ve diğer görünüm hataları bu yöntem çağrılarak raporlanır. Bir kez uyguladığınızda, kapatma işlemi size kalmıştır — bu tür hatalarda görünümü kapatmanızı öneririz; hiçbir gözlemci ayarlanmadığında SDK'nın yerleşik varsayılanı da bunu yapar: ```dart showLineNumbers title="Flutter" void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { // log the error and dismiss the broken view view.dismiss(); } ``` Normal bir durumda render hataları oluşmamalıdır; eğer biriyle karşılaşırsanız lütfen bize bildirin. ### Analitik olayları \{#analytics-events\} İsteğe bağlı `flowViewDidReceiveAnalyticEvent` metodu, bir flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmediğinden, bu metodu uygulamanıza gerek yoktur. ### Observer mode'da satın almaları yönetme \{#handle-purchases-in-observer-mode\} SDK'yı [Observer mode](implement-observer-mode-flutter)'da etkinleştirdiyseniz ve Adapty tarafından oluşturulan bir flow veya paywall sunuyorsanız, SDK satın alma işlemlerini sizin adınıza gerçekleştirmez. Kullanıcı satın alma veya geri yükleme düğmesine dokunduğunda SDK, `AdaptyUIObserverModeResolver`'ınızı çağırır. Tam kurulum için bkz. [Observer mode'da flow sunma](flutter-present-flows-in-observer-mode). ### Sistem isteklerini yönetme \{#handle-system-requests\} `AdaptyUISystemRequestsHandler` (`AdaptyUI().setSystemRequestsHandler(...)` aracılığıyla kaydedilir), bir flow'dan gelen sistem istekleri için ayrılmıştır: işletim sistemi izin istemleri (push bildirimleri veya kamera erişimi gibi) ve App Store inceleme istekleri. Flow'lar henüz bu istekleri tetiklemiyor, dolayısıyla bir handler kaydetmeniz gerekmiyor. Eğer birini kayıt ederseniz, `handlePermission`'ın sınıfın zorunlu metodu olduğunu unutmayın — izni kendi kodunuzla isteyin, ardından `AdaptyUIPermissionResult.granted()` veya `AdaptyUIPermissionResult.denied()` döndürün; `handleAppReviewRequest` ise isteğe bağlıdır.
:::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve paywall render işlemlerine ait olay yönetimini ele almaktadır. Bunların yanı sıra düğme yönetimini de (paywall'ı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini yönetme kılavuzumuza](flutter-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış 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ını (kapatma butonları, URL'ler, ürün seçimleri vb.) ve paywall'da gerçekleştirilen satın alma ile ilgili eylemlerin bildirimlerini içerir. 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. ::: Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIPaywallsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setPaywallsEventsObserver(this); ``` :::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. ::: Aşağıdaki olay örnekleri, her nesnede bulunan özellikleri ve yorumlarda açıklayıcı değerleri göstermektedir. ### Kullanıcı tarafından tetiklenen olaylar #### Paywall göründü \{#paywall-appeared\} Bu yöntem, paywall görünümü ekranda gösterildiğinde çağrılır. :::note iOS'ta, ayrıca kullanıcı bir paywall içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve web paywall uygulama içi tarayıcıda açıldığında da çağrılır. ::: ```dart showLineNumbers title="Flutter" void paywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### Paywall kayboldu \{#paywall-disappeared\} Bu yöntem, paywall görünümü ekrandan kaldırıldığında çağrılır. :::note iOS'ta, bir paywall'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button)'ın uygulama içi tarayıcıdan ekrandan kaybolması durumunda da çağrılır. ::: ```dart showLineNumbers title="Flutter" void paywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu metod çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { // productId is a String: productId; // 'premium_monthly' } ```
#### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma işlemini başlatırsa bu metod çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' product.localizedTitle; // 'Premium Monthly' product.localizedDescription; // 'Premium subscription for 1 month' product.price.amount; // 9.99 (double) product.price.currencyCode; // 'USD' product.price.localizedString; // '$9.99' } ```
#### Tamamlanan satın alma \{#finished-purchase\} Bu metot, bir satın alma işlemi başarıyla tamamlandığında, kullanıcı satın alma işlemini iptal ettiğinde veya satın alma işlemi beklemede göründüğünde çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ```
Olay örnekleri (Genişletmek için tıklayın) ```dart void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) break; case AdaptyPurchaseResultPending(): // no additional data break; case AdaptyPurchaseResultUserCancelled(): // no additional data break; } } ```
Bu durumda ekranı kapatmanızı öneririz. Bir paywall ekranını kapatma hakkında ayrıntılı bilgi için [Düğme eylemlerine yanıt verme](flutter-handle-paywall-actions) bölümüne bakın. #### Web ödeme gezintisi 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 gezinti girişimlerinin her ikisini de kapsar: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **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) ```dart void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { // product — AdaptyPaywallProduct?: product?.vendorProductId; // 'premium_monthly' if (error == null) { // navigation succeeded } else { // error — AdaptyError: error.code; // AdaptyErrorCode.networkFailed (2005) error.message; // 'Network request failed' error.detail; // platform-specific underlying error, or null } } ```
#### Başarısız satın alma \{#failed-purchase\} Bu yöntem, bir satın alma işlemi başarısız olduğunda (örneğin, ödeme sorunları veya ağ hataları nedeniyle) çağrılır. Kullanıcının iptal ettiği veya beklemedeki işlemler için **tetiklenmez**; bunlar `paywallViewDidFinishPurchase` tarafından işlenir: ```dart showLineNumbers title="Flutter" void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } ```
Etkinlik örneği (Genişletmek için tıklayın) ```dart void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' // error — AdaptyError: error.code; // AdaptyErrorCode.productPurchaseFailed (1006) error.message; // 'Product purchase failed.' error.detail; // platform-specific underlying error, or null } ```
#### Geri yükleme başlatıldı \{#started-restore\} Bir kullanıcı geri yükleme işlemini başlatırsa bu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### Başarılı geri yükleme \{#successful-restore\} Bir satın alma başarıyla geri yüklenirse şu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) profile.subscriptions['premium_monthly']?.isActive; // true profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) } ```
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](flutter-listen-subscription-changes) konusuna, paywall ekranını nasıl kapatacağınızı öğrenmek için [Düğme eylemlerine yanıt verme](flutter-handle-paywall-actions) konusuna bakın. #### Geri yükleme başarısız oldu \{#failed-restore\} Bir satın alma geri yüklemesi başarısız olursa bu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.receiveRestoredTransactionsFailed (1011) error.message; // 'Error occurred in the process of restoring purchases.' error.detail; // platform-specific underlying error, or null } ```
### Veri getirme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürün dizisini geçmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa AdaptyUI, hatayı şu metodu çağırarak bildirir: ```dart showLineNumbers title="Flutter" void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } ```
Olay örneği (Genişletmek için tıklayın) ```dart void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.productRequestFailed (1002) error.message; // 'Unable to fetch available In-App Purchase products at the moment.' error.detail; // platform-specific underlying error, or null } ```
#### Render hataları \{#rendering-errors\} Arayüz oluşturma sırasında bir hata oluşursa, bu metot çağrılarak hata bildirilir. Varsayılan olarak (v3.15.2'den itibaren), oluşturma hatası meydana geldiğinde paywall otomatik olarak kapatılır; ancak gerekirse bu davranışı değiştirebilirsiniz. ```dart showLineNumbers title="Flutter" void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // Default behavior: view.dismiss() // Override with custom logic if needed, for example: // - Log the error // - Show an error message to the user } ```
Etkinlik örneği (Genişletmek için tıklayın) ```dart void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.jsException (4105) error.message; // 'An exception was thrown from JS during AdaptyUI flow execution.' error.detail; // platform-specific underlying error, or null // Default behavior: view.dismiss() } ```
Normal şartlarda böyle hatalarla karşılaşılmamalıdır; eğer bununla karşılaşırsanız lütfen bize bildirin.
--- # File: flutter-use-fallback-paywalls --- --- title: "Flutter - Yedek paywall kullanımı" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucularına ulaşılamadığında ne yapılacağını öğrenin" --- :::warning Yedek paywalllar Flutter SDK v2.11 ve sonrası tarafından 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 dosyalarını projenin kök dizinindeki `assets` klasörüne ekleyin. 2. Hedef paywall veya onboarding'i almadan **önce** `.setFallback` metodunu çağırın. ```dart showLineNumbers title="Flutter" final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { await Adapty().setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parametreler: | Parametre | Açıklama | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **assetId** | Yedek yapılandırma dosyasının yolu. | :::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: flutter-localizations-and-locale-codes --- --- title: "Flutter SDK'da yerelleştirmeleri ve yerel ayar kodlarını kullanma" description: "Global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin." --- ## Bu neden önemli \{#why-this-is-important\} Adapty bir flow için yerelleştirme seçerken ve özel paywall için remote config okurken locale kodları devreye girer. Locale kodları karmaşık bir yapıya sahiptir ve platformdan platforma farklılık gösterebilir; bu nedenle Adapty desteklediği her platformda tek bir iç standarda dayanır. Bu standardı anlamak, bir kullanıcının hangi yerelleştirmeyi alacağını önceden tahmin etmenizi sağlar. ## Adapty'de dil kodu standardı \{#locale-code-standard-at-adapty\} Dil kodları için Adapty, [BCP 47 standardının](https://en.wikipedia.org/wiki/IETF_language_tag) hafifçe değiştirilmiş bir versiyonunu kullanır: her kod, tire ile ayrılmış küçük harf alt etiketlerinden 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, kullanıcının yerel ayarıyla eşleşen lokalizasyonu ararken şu adımları izler: 1. Yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgiyle (`-`) değiştirilir 2. Adapty, tam olarak eşleşen yerel ayar koduyla lokalizasyonu arar 3. Eşleşme bulunamazsa, Adapty ilk kısa çizgiden önceki alt dizeyi alır (`pt-br` için `pt`) ve eşleşen lokalizasyonu arar 4. Yine eşleşme bulunamazsa, Adapty varsayılan `en` lokalizasyonunu döndürür Bu şekilde `'pt_BR'`, `pt-BR` ve `pt-br` hepsi aynı lokalizasyona karşılık gelir. ## Yerelleştirmeleri Uygulamak \{#implementing-localizations\} SDK v4'te bir flow çekerken locale kodu iletmezsiniz. - **Flow Builder ve Paywall Builder paywalls'ları**: Adapty, yerelleştirmeyi cihazdan ve builder'da yapılandırdığınız yerelleştirmelerden otomatik olarak çözer. Flow'u `createFlowView` ile render edin — locale koduna gerek yok. - **Özel (remote config) paywalls'lar**: `getFlow`, yapılandırılmış tüm yerelleştirmeleri `flow.remoteConfigs` içinde döndürür. Her girdinin bir `locale` kodu ve config içeriği (`data` dizesi veya ayrıştırılmış `dictionary`) bulunur. Kullanıcıya uyan girdiyi kendi yedek mantığınızla seçin: ```dart showLineNumbers final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final config = flow.remoteConfigs.firstWhereOrNull((c) => c.locale == 'en') ?? flow.remoteConfig; // the first remote config, if present // read your values from config?.dictionary ``` Yukarıdaki yerel ayar kodu eşleştirme kuralları, Adapty'nin her remote config üzerinde depolanan `locale` kodlarını nasıl normalleştirdiğini açıklar. ## Bu neden önemli \{#why-this-is-important\} Locale 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. Locale kodları karmaşık olup platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlar için dahili bir standart kullanıyoruz. Ancak bu kodlar karmaşık olduğundan, sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; böylece her zaman beklediğinizi alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için [BCP 47 standardının](https://en.wikipedia.org/wiki/IETF_language_tag) hafifçe değiştirilmiş bir versiyonunu kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Birkaç örnek: `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'sından yerel ayar koduyla birlikte bir çağrı aldığında ve bir paywall için ilgili 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ştirmeyi arayız 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dizeyi alırız (`pt-br` için `pt`) ve eşleşen yerelleştirmeyi arayız 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesini döndürürüz 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 yöntem \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, büyük ihtimalle projenizde zaten yerelleştirilmiş string dosyalarıyla çalışıyorsunuzdur. Bu durumda, her bir dosyaya ilgili yerelleştirme için hedeflenen Adapty locale kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtara karşılık gelen değeri şu şekilde çıkarabilirsiniz: ```dart showLineNumbers // 1. app_en.arb, app_es.arb, app_pt_br.arb dosyalarınızı düzenleyin /* app_en.arb */ "adapty_paywalls_locale": "en", /* app_es.arb */ "adapty_paywalls_locale": "es", /* app_pt_br.arb */ "adapty_paywalls_locale": "pt-br", // 2. Locale kodunu çıkarın ve kullanın final locale = AppLocalizations.of(context)!.adapty_paywalls_locale; // locale kodunu AdaptyUI.getViewConfiguration veya Adapty.getPaywall metoduna iletin ``` Bu sayede uygulamanızın her kullanıcısı için hangi yerelleştirmenin alınacağını tam olarak kontrol edebilirsiniz. ## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça yerel ayar kodu tanımlamak yerine benzer (ama özdeş olmayan) sonuçlar elde edebilirsiniz. Bu yaklaşımda, platformun sağladığı başka nesnelerden yerel ayar kodunu çıkarırsınız: ```dart showLineNumbers final locale = Localizations.localeOf(context).languageCode; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşımı önermiyoruz; bunun birkaç nedeni var: 1. iOS'ta tercih edilen diller ile mevcut yerel ayar özdeş değildir. Yerelleştirmenin doğru şekilde seçilmesini istiyorsanız, ya Apple'ın mantığına güvenmeniz gerekir (bu, yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda kutudan çıkar gibi çalışır) ya da bunu kendiniz yeniden oluşturmanız gerekir. 2. Adapty'nin sunucusunun tam olarak ne alacağını öngörmek zordur. Örneğin iOS'ta, bir cihazdan `ar_OM@numbers='latn'` gibi bir yerel ayar elde edip sunucumuza göndermeniz mümkündür. Bu çağrı için aradığınız `ar-om` yerelleştirmesini değil, büyük olasılıkla beklemediğiniz `ar` yerelleştirmesini alırsınız. Yine de bu yaklaşımı kullanmaya karar verirseniz, tüm ilgili kullanım senaryolarını kapsadığınızdan emin olun. --- # File: flutter-web-paywall --- --- title: "Flutter SDK'da web paywalllarını uygulama" description: "App Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall kurun." --- :::important Başlamadan önce [kontrol panelinde web paywallınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya daha yeni bir sürümünü yüklediğinizden emin olun. ::: Kendi geliştirdiğiniz bir paywall ile çalışıyorsanız, SDK metodunu kullanarak web paywalllarını yönetmeniz gerekir. `.openWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'ı, kullanıcının yönlendirildiği 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, ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` metodunu çağırır. Bu sayede ödeme başarılı olup erişim hakları güncellendiğinde, abonelik uygulamada neredeyse anında etkinleşir. ```dart showLineNumbers title="Flutter" try { await Adapty().openWebPaywall(product: ); // The web paywall will be opened } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` :::note `openWebPaywall` metodunun iki versiyonu vardır: 1. `openWebPaywall(product)` — URL'leri paywall'a göre oluşturur ve ürün verilerini de URL'lere ekler. 2. `openWebPaywall(paywall)` — URL'leri paywall'a göre oluşturur ancak ürün verilerini URL'lere eklemez. Adapty paywall'ındaki ürünler web paywall'ındaki ürünlerden farklıysa bunu kullanın. SDK v4'te `paywall` parametresi, getirilen flow'un bir paywall varyasyonu olan `AdaptyFlowPaywall` alır. İndeks kullanmadan önce `flow.paywalls`'ın boş olmadığını kontrol edin; örneğin `flow.paywalls[0]`. ::: #### Hataları yönetme \{#handle-errors\} | Hata | Açıklama | Önerilen işlem | |-----------------------------------------|--------------------------------------------------------------|-----------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Paywall için bir web satın alma URL'si yapılandırılmamış | Paywallın Adapty Kontrol Paneli'nde doğru yapılandırıldığını kontrol edin | | AdaptyError.productWithoutPurchaseUrl | Ürün için bir web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın | | AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun | | AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler düzgün şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimde olduğunu doğrulayın | ## Web paywall'larını uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywall'larını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, web paywall'ları harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sağlamak için web paywall'larını uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanızın içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `in` parametresini `.inAppBrowser` olarak ayarlayın: ```dart showLineNumbers try { await Adapty().openWebPaywall( product: , openIn: AdaptyWebPresentation.inAppBrowser, ); // The web paywall will be opened in the in-app browser } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` --- # File: flutter-troubleshoot-paywall-builder --- --- title: "Flutter SDK'da Paywall Builder Sorun Giderme" description: "Flutter SDK'da Paywall Builder Sorun Giderme" --- Bu rehber, Flutter SDK'da Adapty Paywall Builder ile tasarlanan 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**: `createPaywallView` metodu paywall yapılandırmasını alamıyor. **Neden**: Paywall, Paywall Builder'da cihazda gösterim için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. ## Paywall görüntülenme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntülenme sayısı beklenenin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (Flutter SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz; Paywall Builder veya Flow Builder kullanıyorsanız bu, görüntülenme sayısını iki katına çıkarır. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitikler otomatik olarak takip edilir; bu nedenle söz konusu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (Flutter SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder kaynaklı sorunlar yaşıyorsunuz. **Çözüm**: Gerekirse [migration rehberlerini](flutter-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde giderilmiştir. --- # File: flutter-present-flows-in-observer-mode --- --- title: "Flutter SDK'da Observer modunda flow'ları sunma" description: "Flutter uygulamanızda Observer modunda flow'ları ve Paywall Builder paywall'larını sunun; satın almaları kendi kodunuzla yönetin." --- Builder'ı kullanarak bir flow veya paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, hem ne gösterileceğini hem de nasıl gösterileceğini 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, [Flow'ları ve paywall'ları görüntüleme](flutter-present-paywalls) konusuna bakın. ::: :::info Bu özellik Adapty Flutter SDK 4.0 veya sonrasını gerektirir — daha önce yalnızca native iOS ve Android SDK'larında mevcuttu. Yükseltmek için [migration kılavuzuna](migration-to-flutter-sdk-v4) bakın. :::
Flow'ları sunmaya başlamadan önce (Genişletmek için tıklayın) 1. Adapty'yi [App Store ile](initial_ios) ve [Google Play ile](initial-android) ilk entegrasyonunu kurun. 2. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. [Flutter SDK kurulum kılavuzuna](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'lar veya paywalllar yapılandırın](create-paywall) ve bunlara ürün atayın. 5. [Placement'lar oluşturun ve flow'larınızı veya paywalllarınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını çekin](flutter-get-pb-paywalls).
Observer modunda SDK, satın alma işlemlerini sizin adınıza gerçekleştirmez. Kullanıcı Adapty tarafından render edilen bir flow veya paywall'da satın alma ya da geri yükleme butonuna dokunduğunda SDK, `AdaptyUIObserverModeResolver`'ınızı çağırır — satın alma veya geri yükleme işlemini orada kendi kodunuzla gerçekleştirin. 1. `AdaptyUIObserverModeResolver`'ı uygulayın: ```dart showLineNumbers title="Flutter" class MyObserverModeResolver extends AdaptyUIObserverModeResolver { @override void observerModeDidInitiatePurchase( AdaptyUIFlowView view, AdaptyPaywallProduct product, void Function() onStartPurchase, void Function() onFinishPurchase, ) { onStartPurchase(); // the view shows its loading indicator // make the purchase with your own code, then: onFinishPurchase(); // the view hides the loading indicator } @override void observerModeDidInitiateRestore( AdaptyUIFlowView view, void Function() onStartRestore, void Function() onFinishRestore, ) { onStartRestore(); // restore purchases with your own code, then: onFinishRestore(); } } ``` `observerModeDidInitiatePurchase` metodu kullanıcının bir satın alma başlattığını, `observerModeDidInitiateRestore` ise kullanıcının bir geri yükleme başlattığını size bildirir. Buna yanıt olarak kendi özel satın alma veya geri yükleme flow'unuzu tetikleyin. Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'a bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi gösterme gibi düzgün flow davranışı için gereklidir: | Callback | Açıklama | | :----------------- | :---------------------------------------------------------------------------------------------- | | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | 2. Herhangi bir ekran gösterilmeden önce resolver'ı kaydedin: ```dart showLineNumbers title="Flutter" AdaptyUI().setObserverModeResolver(MyObserverModeResolver()); ``` 3. Flow görünümünü her zamanki gibi oluşturun ve gösterin: [flow'u alın ve görünümünü oluşturun](flutter-get-pb-paywalls), ardından [gösterin](flutter-present-paywalls). Ekstra parametre gerekmez — resolver bir kez kaydedildiğinde, Adapty tarafından render edilen her flow veya paywall, satın alma ve geri yüklemeleri bu resolver üzerinden yönlendirir. :::warning [İşlemi bildirmeyi ve paywall ile ilişkilendirmeyi](report-transactions-observer-mode-flutter) unutmayın. Aksi takdirde Adapty işlemi tanımayacak ve satın almanın kaynak paywall'ını belirleyemeyecektir. ::: --- # File: flutter-quickstart-manual --- --- title: "Flutter 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 Flutter paywall'larınıza entegre edin." --- Bu rehber, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall uygulamasının tam kontrolünü elinizde tutarken, Adapty SDK ürünleri getirir, yeni satın almaları gerçekleştirir ve önceki satın almaları geri yükler. Bu rehber Adapty Flutter SDK v4 API'lerini kullanır — v3 kullanıyorsanız, karşılık gelen metod adları için [migration rehberine](migration-to-flutter-sdk-v4) bakın. :::important **Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız, [Adapty Paywall Builder](flutter-quickstart-paywalls)'ı kullanın. Paywall Builder ile kodsuz görsel bir editörde paywall'lar oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan Önce \{#before-you-start\} ### Ürünleri ayarlayın \{#set-up-products\} 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) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywalllar aracılığıyla ulaşılır; bu yapı sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. SDK v4'te bir placement için paywall varyantları bir **flow** nesnesi tarafından taşınır — flow'u çekip ürünlerini sorgularsınız. - [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yapı A/B testleri yürütmeyi ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır. Bu kavramları, kendi özel paywall'unuzla çalışsanız bile anladığınızdan emin olun. Bunlar, temelde uygulamanızda sattığınız ürünleri yönetmenin bir yoludur. Özel paywall'unuzu 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 [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetme \{#manage-users\} Backend kimlik doğrulaması kullanıp kullanmamak tamamen size bağlıdır. Ancak Adapty SDK, anonim ve kimliği doğrulanmış kullanıcıları farklı şekilde ele alır. Ayrıntıları öğrenmek ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik doğrulama hızlı başlangıç kılavuzunu](flutter-quickstart-identify) okuyun. ## 1. Adım. Ürünleri alın \{#step-1-get-products\} Özel paywallınız için ürünleri almak üzere şunları yapmanız gerekir: 1. [Placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın. 2. Bu flow için ürünler dizisini `getPaywallProducts` metodunu kullanarak alın. ```dart showLineNumbers Future loadPaywall() async { try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final products = await Adapty().getPaywallProducts(flow: flow); // Use products to build your custom paywall UI } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 2. Satın almaları kabul etme \{#step-2-accept-purchases\} Kullanıcı özel paywallınızdaki bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```dart showLineNumbers Future purchaseProduct(AdaptyPaywallProduct product) async { try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // Purchase successful, profile updated break; case AdaptyPurchaseResultUserCancelled(): // User canceled the purchase break; case AdaptyPurchaseResultPending(): // Purchase is pending (e.g., user will pay offline with cash) break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 3. Satın almaları geri yükle \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik içeren 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 butonuna bastığında `restorePurchases` metodunu çağırın. Bu işlem, kullanıcının satın alma geçmişini Adapty ile senkronize eder ve güncel profili döndürür. ```dart showLineNumbers Future restorePurchases() async { try { final profile = await Adapty().restorePurchases(); // Restore successful, profile updated } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 4. Abonelik durumunu kontrol edin \{#step-4-check-the-subscription-status\} Bir satın alma veya geri yükleme işleminin ardından, paywall'ı gösterip göstermeyeceğinize ya da ücretli özellikleri açıp açmayacağınıza karar vermek için kullanıcının [access level](access-level) durumunu kontrol edin. `makePurchase` ve `restorePurchases` metodları zaten güncellenmiş profili döndürür; uygulamanın başka bir yerinde mevcut duruma ihtiyaç duyduğunuzda `getProfile` metodunu kullanın: ```dart showLineNumbers Future hasPremiumAccess() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['premium']?.isActive ?? false; } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } return false; } ``` Abonelik durumunu kontrol etmenin ve gerçek zamanlı güncellemeleri dinleme dahil izlemenin daha fazla yolu için bkz. [Abonelik durumunu kontrol etme](flutter-check-subscription-status). ## 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. Paywall üzerinden test satın alma işlemini tamamlayabildiğinizden emin olmak için [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da satın almalarınızı test edin. Bunun gerçek bir uygulamada nasıl çalıştığını görmek için örnek uygulamamızdaki [PurchasesObserver](https://github.com/adaptyteam/AdaptySDK-Flutter/blob/master/example/lib/purchase_observer.dart)'a göz atabilirsiniz; bu örnekte hata yönetimi, UI gözlemcileri ve kapsamlı SDK entegrasyonuyla birlikte satın alma işleme akışı gösterilmektedir. --- # File: fetch-paywalls-and-products-flutter --- --- title: "Flutter SDK'da remote config paywallları için paywall ve ürünleri getirme" description: "Kullanıcı monetizasyonunu artırmak için Adapty Flutter SDK'da paywall ve ürünleri getirin." --- Remote config ve özel paywallları sergilemeden önce, bunlarla ilgili bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu lütfen unutmayın. Flow'ları ve Paywall Builder ile özelleştirilmiş paywallları almak için [Flow'ları ve paywallları al](flutter-get-pb-paywalls) bölümüne 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 paywall ve ürün bilgilerini almaya 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 bu paywalla ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-flutter).
## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonu olarak işlev görür. Bu çapraz platform ürünler, paywall'lara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri görüntülemek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan koda yazmanız gereken tek ID, placement ID'dir. Paywalllar 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, yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde 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 ulaşmasını sağladığı için bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu 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 verilere ulaşamayabilir, 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 ö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 temizleme yapıldığında temizlendiğini unutmayın.

Adapty SDK, paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywall'lar](flutter-use-fallback-paywalls). Paywall'ları daha hızlı yüklemek için CDN, CDN'e ulaşılamadığı durumlar için ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman paywall'larınızın en güncel 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 ö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şuyor olabilir.

| :::note v4'te `getFlow`, `locale` parametresi almaz. Özel paywalllar için tüm mevcut yerelleştirmeler flow'un remote config'lerinde (`flow.remoteConfigs`) döner — kullanıcının cihaz veya uygulama ayarıyla eşleşeni seçin. Bkz. [Yerelleştirmeler ve locale kodları](flutter-localizations-and-locale-codes). ::: Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Flow'un tanımlayıcılarını (`instanceIdentity`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve remote config'leri (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## Ürünleri getir \{#fetch-products\} Flow'u aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(flow: flow); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısını, ürün adını, fiyatı, para birimini, abonelik süresini ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; tüm mevcut özellikler için bağlantılı belgeye başvurun. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın yerel 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örüntülemek için `product.price.localizedString` kullanın. Bu yerelleştirme, cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz. Değer yerel para biriminde sağlanır. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (örn. hafta, ay, yıl vb.) görüntülemek için `product.subscription?.localizedPeriod` 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.subscription?.period` kullanın. Buradan `unit` enum'una erişerek uzunluğu (gün, hafta, ay, yıl veya bilinmeyen) alabilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin, üç aylık bir abonelik için unit özelliğinde `AdaptyPeriodUnit.month`, numberOfUnits özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Aboneliğin başlangıç teklifi içerdiğini gösteren bir rozet veya başka bir gösterge eklemek için `product.subscription?.offer?.phases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere iki adede kadar indirim aşaması içerebilir. Her aşama nesnesi şu yararlı özellikleri içerir:
• `paymentMode`: `AdaptyPaymentMode.freeTrial`, `AdaptyPaymentMode.payAsYouGo`, `AdaptyPaymentMode.payUpFront` ve `AdaptyPaymentMode.unknown` değerlerine sahip bir enum. Ücretsiz denemeler `AdaptyPaymentMode.freeTrial` türünde olur.
• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemeler için burada `0` değerini arayın.
• `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarına göre yerelleştirilmiş olarak açıklayan bir dize. Örneğin, üç günlük bir deneme teklifi bu alanda `3 days` olarak gösterilir.
• `subscriptionPeriod`: Alternatif olarak, bu özellikle teklif döneminin ayrıntılarını tek tek alabilirsiniz. Teklifler için önceki bölümde açıklanan şekilde çalışır.
• `localizedSubscriptionPeriod`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim abonelik dönemi. | ## Varsayılan kitle flow'u ile flow getirmeyi hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Flow'lar genellikle 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 placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Bu gibi 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 gidermek için, belirtilen placement'ın **All Users** kitlesi için flow'unu getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-flutter#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi `getFlow` metoduyla flow'u getirmek olduğunu anlamak kritik öneme sahiptir. :::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 için (mevcut ve gelecekteki) farklı paywalllar göstermeniz gerekiyorsa, çeşitli zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywalllarla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize dayalı hedefleme dahil) kaybettiğiniz anlamına gelir. Bu dezavantajları kabul edip daha hızlı flow çekme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-flutter#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` | 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. 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 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 son verilere 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 boyunca 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 temizleme yapıldığında temizlendiğini unutmayın.

|
Remote config ve özel paywallları göstermeden önce, bunlara ait bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları çekme konusunda rehberlik için [Paywall Builder paywalllarını ve yapılandırmalarını çekme](flutter-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 çekmeye 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ünleri 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-flutter) mobil uygulamanıza.
## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'deki ürünlerin bir kombinasyonudur. Bu platformlar arası ürünler, belirli mobil uygulama placement'larında gösterilebilmesi için paywalllarla entegre edilir. Ürünleri görüntülemek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini koda gömmayın.** Koda gömmeniz gereken tek ID, placement ID'sidir. Paywalllar 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; bugün bir paywall iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini göstermeniz gerekir. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` | 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. | | **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 dili, ikincisi ise bölgeyi belirtir.

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

Yerel ayar kodları ve önerilen kullanım şekli hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) sayfasına bakın.

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

SDK varsayılan olarak verileri sunucudan yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Bu yaklaşımı öneriyoruz çü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` seçeneğini kullanmayı değerlendirin. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerini azaltmak amacıyla oturum sırasında güvenle kullanılabilir.

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

Adapty SDK, paywallları iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](flutter-use-fallback-paywalls). Ayrıca paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı 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şılırsa önbellekteki 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.

| Ürün ID'lerini koda gömmeyIn! Paywalllar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz denemeler 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, kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Koda gömmeniz gereken tek şey placement ID'sidir. 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://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywallı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özelliklerle birlikte [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) 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ştirme, cihazın dilini değil, kullanıcının seçtiği mağaza ülkesini baz alır. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın dil ayarlarına 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 Periyodu** | Periyodu (ör. hafta, ay, yıl vb.) göstermek için `product.subscription?.localizedPeriod` kullanın. Bu yerelleştirme cihazın diline göre yapılır. Abonelik periyodunu programatik olarak almak için `product.subscription?.period` kullanın. Buradan `unit` enum'una erişerek uzunluğu (yani gün, hafta, ay, yıl veya bilinmiyor) öğrenebilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `AdaptyPeriodUnit.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 amacıyla rozet veya başka bir gösterge eklemek için `product.subscription?.offer?.phases` ö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 bulunur:
• `paymentMode`: `AdaptyPaymentMode.freeTrial`, `AdaptyPaymentMode.payAsYouGo`, `AdaptyPaymentMode.payUpFront` ve `AdaptyPaymentMode.unknown` değerlerine sahip bir enum. Ücretsiz denemeler `AdaptyPaymentMode.freeTrial` türünde olur.
• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemeler için burada `0` arayın.
• `localizedNumberOfPeriods`: Teklifin süresini cihazın diline göre yerelleştirilmiş biçimde açıklayan bir string. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak görünür.
• `subscriptionPeriod`: Alternatif olarak, teklif periyodunun ayrıntılarını bu özellikle alabilirsiniz. Teklifler için bir önceki bölümde açıklanan yöntemle aynı şekilde çalışır.
• `localizedSubscriptionPeriod`: Kullanıcının diline göre biçimlendirilmiş indirim abonelik periyodu. | ## Varsayılan kitle paywallıyla veri çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında çekilir, bu nedenle bu işlemi 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 çekme işlemi istediğinizden daha uzun sürebilir. Bu durumlarda, hiç paywall göstermemek yerine kullanıcı deneyimini sorunsuz kılmak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesine ait paywallını getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products-flutter#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywallı çekmek olduğunu göz önünde bulundurun. :::warning Neden `getPaywall` kullanmanızı öneriyoruz? `getPaywallForDefaultAudience` metodunun bazı önemli dezavantajları 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 tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywalllarla sorun yaşamasını kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar, **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı paywall çekme işleminden yararlanmak istiyorsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-flutter#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` metodu Flutter SDK 3.2.0 sürümünden itibaren kullanılabilir. ::: | 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. | | **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 dili, ikincisi ise bölgeyi belirtir.

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

Yerel ayar kodları ve önerilen kullanım şekli hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) sayfasına bakın.

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

SDK varsayılan olarak verileri sunucudan yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Bu yaklaşımı öneriyoruz çü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` seçeneğini kullanmayı değerlendirin. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerini azaltmak amacıyla oturum sırasında güvenle kullanılabilir.

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

|
--- # File: present-remote-config-paywalls-flutter --- --- title: "Flutter SDK'da remote config ile tasarlanan paywallı render etme" description: "Adapty Flutter SDK'da remote config paywalllarını nasıl sunacağınızı keşfedin ve kullanıcı deneyimini kişiselleştirin." --- Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın koduna render işlemi eklemeniz 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. Remote config aracılığıyla yapılandırılmış özel paywall'ınızı göstermek için remote config'i çekme yöntemi sunuyoruz; nasıl kullanacağınız tamamen size kalmış. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} v4'te flow, `remoteConfigs` listesi taşır — yapılandırılmış her yerelleştirme için bir remote config. Kullanıcının yerel ayarıyla eşleşen girişi seçin ve gerekli değerleri çıkarın. Doğru yerelleştirmeyi seçmek için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) bölümüne bakın. ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // one entry per configured localization; fall back to the first one final config = flow.remoteConfigs.firstWhereOrNull((c) => c.locale == 'en') ?? flow.remoteConfig; final String? headerText = config?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // 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 telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunulur. :::warning Adapty analytics'in huniler ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde paywall görüntüleme olayını kaydettiğinizden emin olun. ::: Paywallı görüntülemeyi tamamladıktan sonra satın alma akışını kurmaya 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](flutter-making-purchases) sayfasını okuyun. [Yedek paywall adı verilen bir yedek paywall oluşturmanızı](flutter-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilecek ve bu durumlarda bile sorunsuz bir deneyim sağlayacaktır. ## Paywall görüntüleme olaylarını takip edin \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da, paywall görüntüleme olaylarını kaydetmek sizin müdahalenizi gerektiriyor; çünkü bir kullanıcının paywall'ı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir paywall görüntüleme olayı kaydetmek için `.logShowFlow(flow: flow)` metodunu çağırmanız yeterli; bu işlem, funnel'larınızdaki ve A/B testlerinizdeki paywall metriklerinize yansıyacaktır. :::important [Builder](adapty-paywall-builder) ile oluşturulan flow'ları veya paywall'ları görüntülüyorsanız `.logShowFlow(flow: flow)` çağrısı yapmanıza gerek yoktur. ::: ```dart showLineNumbers try { await Adapty().logShowFlow(flow: flow); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- |:----------------------------------------------------------------------| | **flow** | zorunlu | Bir `AdaptyFlow` nesnesi. | Remote config kullanarak bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulamanızın kodunda görüntüleme işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywalla nelerin dahil edileceğini ve görünümünün nasıl olacağını tamamen siz belirlersiniz. Remote config aracılığıyla yapılandırılmış özel paywallınızı göstermek için uzak yapılandırmayı çekmenizi sağlayan 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 çıkarın. ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 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 telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olarak farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunun. :::warning Adapty analitiğinin huni ve A/B testi için bilgileri yakalayabilmesi amacıyla aşağıda açıklandığı şekilde paywall görüntüleme olayını kaydettiğinizden emin olun. ::: Paywalli görüntüledikten sonra, satın alma akışını ayarlamaya devam edin. Kullanıcı bir satın alma işlemi 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](flutter-making-purchases) bölümünü okuyun. [Yedek paywall adı verilen bir yedek paywall oluşturmanızı](flutter-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilerek bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme etkinliklerini takip edin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplasak da, paywall görüntülemelerini kaydetmek sizin müdahalenizi gerektirir; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilirsiniz. Bir paywall görüntüleme etkinliğini kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu işlem huni ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Paywall builder](adapty-paywall-builder) ile oluşturulan paywallları görüntülüyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | --- # File: flutter-making-purchases --- --- title: "Flutter SDK ile mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın almaları ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları görüntülemek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak, paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, bu paywall'ları yalnızca göstermek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, bir satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir yöntem kullanmanız gerekir. Bu yöntem, kullanıcıların paywall'larla etkileşime geçmesi ve istedikleri işlemleri gerçekleştirmesi için bir geçit görevi görür. Kullanıcının satın almaya çalıştığı ürün için paywall'ınızda aktif bir promosyon teklifi varsa, Adapty satın alma sırasında bunu otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik olarak uygulanabilmesi için Paywall Builder kullanılarak oluşturulmuş paywall'ları kullanmanız gerektiğini unutmayın. Diğer durumlarda, [iOS'ta başlangıç teklifi uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekecektir. Bu adımı atlamak, yayın sırasında uygulamanızın reddedilmesine yol açabilir. Bunun yanı sıra, başlangıç teklifine hak kazanan kullanıcılardan tam ücret alınmasına neden olabilir. ::: [Başlangıç yapılandırmasını](quickstart) tek bir adımı atlamadan tamamladığınızdan emin olun. Bu olmadan satın almaları doğrulayamayız. ## Satın alma işlemi gerçekleştirme \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın alma işlemleri otomatik olarak gerçekleştirilir; 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](flutter-implement-paywalls-manually) göz atın. ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve tek seferlik satın almaları hakkında kapsamlı bilgi sağlar.

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

| :::warning **Not:** Apple'ın StoreKit sürümü v2.0'ın altında ve Adapty SDK sürümü v2.9.0'ın altında kullanıyorsanız, bunun yerine [Apple App Store paylaşılan sırrı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem şu anda Apple tarafından kullanımdan kaldırı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 gerçekleşeceği uygulama mağazasına göre değişir: - App Store'da abonelik, abonelik grubu içinde otomatik olarak güncellenir. Kullanıcı bir gruptan abonelik satın alırken başka bir gruptan aktif aboneliği varsa, her iki abonelik de aynı anda aktif olur. - 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: ```dart showLineNumbers try { final subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( 'OLD_PRODUCT_ID', AdaptyAndroidSubscriptionUpdateReplacementMode.immediateWithTimeProration, ); final result = await Adapty().makePurchase( product: product, parameters: AdaptyPurchaseParameters( subscriptionUpdateParams: subscriptionUpdateParams, ), ); // başarılı çapraz yükseltme } on AdaptyError catch (adaptyError) { // Hatayı işle } catch (e) { // Hatayı işle } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :------- |:--------------------------------------------------------------------------------------------------------| | **parameters** | zorunlu | `subscriptionUpdateParams` alanı bir [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html) nesnesine ayarlanmış `AdaptyPurchaseParameters` nesnesi. | Google Developer belgelerinde abonelikler ve değiştirme modları hakkında daha fazla bilgi edinebilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değiştirme modları için ö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 faturalandırma dönemi sona erdiğinde gerçekleşir. ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\}
Teklif kodları hakkında Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın.
Uygulamanızda kod kullanma sayfasını görüntülemek için: ```dart showLineNumbers try { await Adapty().presentCodeRedemptionSheet(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` :::danger Gözlemlerimize göre, bazı uygulamalarda Teklif Kodu Kullanma sayfası güvenilir şekilde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için aşağıdaki formattaki URL'yi açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ### Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli plan](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin, birkaç aylık yenilenemez bir abonelik), ön ödemeli planlar için [beklemedeki işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleEnablePendingPrepaidPlans(true), ); ``` --- # File: flutter-restore-purchase --- --- title: "Flutter SDK'da mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz bir kullanıcı deneyimi sağlamak için Adapty'de satın almaların nasıl geri yükleneceğini öğrenin." --- Satın Almaları Geri Yükleme, hem iOS hem de Android'de 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, özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywallarda satın almalar, sizin tarafınızdan ek bir kod gerektirmeksizin 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 almaları geri yüklemek için `.restorePurchases()` metodunu çağırın: ```dart showLineNumbers try { final profile = await Adapty().restorePurchases(); if (profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false) { // successful access restore } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------| | **Profile** |

Bir [`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi. Bu model, access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi 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-flutter --- --- title: "Flutter SDK'da Observer modunu uygulayın" description: "Adapty'de observer modunu uygulayarak Flutter SDK'da kullanıcı abonelik etkinliklerini takip edin." --- Kendi satın alma altyapınız zaten varsa ve Adapty'ye tamamen geçmeye hazır değilseniz, [Observer mode](observer-vs-full-mode)'u inceleyebilirsiniz. Temel haliyle Observer Mode, gelişmiş analizler ve attribution ile analitik sistemleriyle sorunsuz entegrasyon sunar. Bu ihtiyacınızı karşılıyorsa, yalnızca şunları yapmanız gerekir: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak etkinleştirin. Kurulum talimatları için [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) sayfasına bakın. 2. Mevcut satın alma altyapınızdan Adapty'ye [işlemleri bildirin](report-transactions-observer-mode-flutter). ## Observer modu kurulumu \{#observer-mode-setup\} Satın alma işlemlerini ve abonelik durumunu kendiniz yönetiyorsanız ve Adapty'yi abonelik olayları ile analitik göndermek için kullanıyorsanız Observer modunu etkinleştirin. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle işlemleri kendiniz yönettiğinizden emin olun. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden bir boolean değeri. Varsayılan değer `false`'tur. | ## Observer Mode'da Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer mode'da bazı ek kurulum adımları gerekir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekecek: 1. [Remote config paywall'lar](present-remote-config-paywalls-flutter) için paywall'ları her zamanki gibi gösterin. 3. Satın alma işlemlerini paywall'larla [ilişkilendirin](report-transactions-observer-mode-flutter). :::tip SDK v4'te, Observer mode'da Adapty tarafından render edilen flow'ları ve paywall'ları da sunabilirsiniz: bir kullanıcı ilgili butona dokunduğunda kendi kodunuzla satın alma veya geri yükleme işlemini gerçekleştirmek için bir `AdaptyUIObserverModeResolver` kaydedin. Bkz. [Observer mode'da flow sunma](flutter-present-flows-in-observer-mode). ::: --- # File: report-transactions-observer-mode-flutter --- --- title: "Flutter SDK'da Observer Mode'da işlemleri raporlama" description: "Flutter SDK'da Adapty Observer Mode'da kullanıcı içgörüleri ve gelir takibi için satın alma işlemlerini raporlayın." --- Observer mode'da, Adapty SDK kendi başına mevcut satın alma sisteminiz üzerinden yapılan satın almaları takip edemez. App Store'daki işlemleri uygulamanızdan manuel olarak bildirmeniz gerekir. Analitik hatalarını önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız son derece önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanarak açıkça bildirin. :::warning **İşlem bildirmeyi atlama!** `reportTransaction` çağırmazsanız, Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, bir işlem bildirirken `variationId`'yi de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```dart showLineNumbers try { // transaction.finish() her çağrıldığında await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // isteğe bağlı ); } on AdaptyError catch (adaptyError) { // hatayı işle } catch (e) { // hatayı işle } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- | ------------------------------------------------------------ | | transactionId | zorunlu |
  • iOS için: İşlemin tanımlayıcısı.
  • Android için: Satın almanın `purchase.getOrderId` string tanımlayıcısı; burada purchase, billing library'nin [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ı. Bunu [AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. |
Observer modunda, Adapty SDK mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan işlemleri raporlamanız veya geri yüklemeniz gerekir. Analitik hatalarını önlemek için bunu uygulamanızı yayınlamadan **önce** ayarlamanız kritik önem taşır. Her işlemi açıkça raporlamak için her iki platformda da `reportTransaction` kullanın; Adapty'nin bunu tanımasını sağlamak için Android'de ek bir adım olarak `restorePurchases` kullanın. :::warning **İşlem raporlamayı ve satın alma geri yüklemeyi atlama!** Bu metotları çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, işlem raporlarken `variationId` değerini ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```dart showLineNumbers // every time when calling transaction.finish() if (Platform.isAndroid) { try { await Adapty().restorePurchases(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- | ------------------------------------------------------------ | | transactionId | 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: String tanımlayıcı (satın almanın purchase.getOrderId değeri; burada purchase, billing library [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ı. Bunu [AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. |
**İşlemleri raporlama** - 3.1.x'e kadar olan sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel raporlama gerekmez. - 3.2 sürümü Observer Mode'u desteklemez. **İşlemleri raporlama** [Mobil Kodda Satın Almaları Geri Yükle](flutter-restore-purchase) sayfasında açıklandığı gibi, Observer Mode'da bir işlemi Adapty'ye bildirmek için `restorePurchases` kullanın. :::warning **İşlem bildirmeyi atlama!** `restorePurchases` çağrısı yapmazsanız, Adapty işlemi tanımaz, analytics'te görünmez ve entegrasyonlara gönderilmez. ::: **Paywall'ları işlemlerle ilişkilendirme** Adapty SDK, satın almaları siz işlediğiniz için satın almaların kaynağını belirleyemez. Bu nedenle, Observer mode'da paywall'lar ve/veya A/B testleri kullanmayı planlıyorsanız, uygulama mağazanızdan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Uygulamanızı yayınlamadan önce bunu doğru şekilde ayarlamanız önemlidir; aksi takdirde analizlerde hatalara yol açar. ```dart final transactionId = transaction.transactionIdentifier final variationId = paywall.variationId try { await Adapty().setVariationId('transactionId', variationId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ```
--- # File: flutter-troubleshoot-purchases --- --- title: "Flutter SDK'da satın alma sorunlarını giderme" description: "Flutter SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, Flutter 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 eksik Google Play Store kurulumuna veya yapılandırma sorunlarına işaret eder. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) 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**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-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` kullanmalı ya da observer modunda satın almaları kendi tarafınızda yönetmelisiniz. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode-flutter) 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 fatura 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 Billing Library hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store belgelerinde daha fazla bilgi edinebilirsiniz: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamadı \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor şeklinde hatalarla 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 yöntem çoğunlukla sandbox ile ilgili satın alma tamamlama işleyicisi 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 [taşıma kılavuzlarını](flutter-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüştür. --- # File: flutter-identifying-users --- --- title: "Flutter SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini geliştirmek için kullanıcıları Adapty'de tanımlayın." --- 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 belirlemeniz gerekir. Kullanıcıları Customer User ID'leriyle [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 belirleme \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, `.activate()` metoduna `customerUserId` parametresi olarak doğrudan geçirebilirsiniz: ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) ); } catch (e) { // handle the error } ``` :::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 belirleme \{#setting-customer-user-id-after-configuration\} SDK yapılandırması sırası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ı anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçtiğinde ortaya çıkar. ```dart showLineNumbers try { await Adapty().identify(customerUserId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` İstek parametreleri: - **Customer User ID** (zorunlu): string formatında kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerini yeniden gönderme Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahip olabilir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmak için otomatik olarak geçiş yapar. Anonim kullanıcıya özel nitelikler veya üçüncü taraf ağlarından attribution verileri gibi herhangi bir veri iletmişseniz, 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 talep etmeniz önemlidir. ::: ### Oturum kapatma ve açma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak istediğiniz zaman kullanıcının oturumunu kapatabilirsiniz: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` Ardından `.identify()` metoduyla kullanıcıyı tekrar oturum açtırabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle birlikte kaydeder, böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulmuş, kararlı bir UUID kullanın ve aynı hesap için cihazlar arasında aynı UUID'yi tekrar kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş olur. Token'ı iki şekilde belirleyebilirsiniz: SDK aktivasyonu sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmeniz gerekir. Yalnızca token'ı geçerseniz, işleme dahil edilmez. ::: ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Gizlenmiş hesap ID'lerini belirleme (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryolarında gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in satın almaları tanımlamasına yardımcı olurken kullanıcı bilgilerini anonim tutar; bu özellikle dolandırıcılığı önleme ve analitik açısından önemlidir. Uygulamanız hassas kullanıcı verileri işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri belirlemeniz gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın almaları takip etmesini sağlar. ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ## 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: flutter-setting-user-attributes --- --- title: "Flutter SDK'da kullanıcı özniteliklerini ayarlama" description: "Daha iyi kitle segmentasyonu sağlamak için Adapty'de kullanıcı özniteliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulama kullanıcılarınıza e-posta, telefon numarası gibi isteğe bağlı öznitelikler ekleyebilirsiniz. Bu öznitelikleri kullanarak kullanıcı [segmentleri](segments) oluşturabilir ya da CRM'de görüntüleyebilirsiniz. ### Kullanıcı özniteliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özniteliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setEmail("email@email.com") ..setPhoneNumber("+18888888888") ..setFirstName('John') ..setLastName('Appleseed') ..setGender(AdaptyProfileGender.other) ..setBirthday(DateTime(1970, 1, 3)); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` `updateProfile` metoduyla daha önce ayarladığınız özniteliklerin sıfırlanmayacağını unutmayı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. ::: ### İ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ı öznitelikleri \{#custom-user-attributes\} Kendi özel özniteliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi seviyesi gibi. Bu öznitelikleri segmentlerde hedefli paywall'lar ve teklifler oluşturmak için kullanabilirsiniz; ayrıca hangi ürün metriklerinin geliri en çok etkilediğini bulmak için analizlerde de işe yarar. ```dart showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```dart showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Bazen önceden hangi özel özniteliklerin ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini aklınızda bulundurun; kullanıcı öznitelikleri farklı cihazlardan herhangi bir anda gönderilebileceğinden, sunucudaki öznitelikler son senkronizasyondan bu yana değişmiş olabilir. ::: ### Sınırlamalar \{#limits\} - Kullanıcı başına en fazla 30 özel öznitelik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ve şunlardan herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakterden oluşan bir string veya float olabilir. --- # File: flutter-listen-subscription-changes --- --- title: "Flutter SDK'da abonelik durumunu kontrol etme" description: "Flutter uygulamanızda müşteri tutundurma oranını artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek oldukça kolaydır. Kodunuza manuel olarak ürün ID'leri 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 (Genişletmek için tıklayın) - iOS için [App Store Sunucu Bildirimlerini](enable-app-store-server-notifications) yapılandırın - Android için [Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN)](enable-real-time-developer-notifications-rtdn) yapılandırın
## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesinin özellikleridir. Uygulamanız başladığında, örneğin [kullanıcıyı tanımlarken](flutter-identifying-users#setting-customer-user-id-on-configuration) profili almanızı ve ardından değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini her seferinde yeniden istek atmadan kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Abonelik durumu güncellemelerini dinleme](flutter-listen-subscription-changes) bölümünde açıklandığı gibi profil değişikliklerini dinleyebilirsiniz. :::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: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- | ------------------------------------------------------------ | | Profile |

Bir [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi. Genellikle, kullanıcının uygulamada premium erişime sahip 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 döndürür. Herhangi bir nedenle (örneğin internet bağlantısı olmaması), 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, access level durumunu öğrenebileceğiniz kullanıcı profilini döndürür. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin bir gazete uygulamanız varsa ve farklı konulara abonelikleri bağımsız olarak satıyorsanız, "sports" ve "science" gibi access level'lar oluşturabilirsiniz. Ancak çoğu durumda tek bir access level yeterlidir; bu durumda varsayılan "premium" access level'ını kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### 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 birkaç ek yapılandırma yapmanız gerekmektedir: ```dart showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adapty ayrıca uygulama başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu erişilemez olsa bile profilin abonelik durumuyla ilgili bilgilere önbellekten ulaşılabilir. Ancak önbellekten doğrudan veri isteği yapılamadığını belirtmek gerekir. SDK, profille ilgili güncellemeleri veya değişiklikleri kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler söz konusu olduğunda, önbellekteki verilerin sunucuyla senkronize kalması için bu değişiklikler önbelleğe gönderilir. --- # File: flutter-deal-with-att --- --- title: "Flutter SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumu ve yönetimini kolaylaştırmak için Flutter'da Adapty'yi kullanmaya başlayın." --- Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama takip yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning Bu değeri, değiştiği anda mümkün olan en kısa sürede göndermenizi kesinlikle öneririz. Ancak bu şekilde veriler, yapılandırdığınız entegrasyonlara zamanında iletilir. ::: --- # File: kids-mode-flutter --- --- title: "Flutter SDK'da Kids Mode" description: "Apple ve Google politikalarına uymak için Kids Mode'u kolayca etkinleştirin. Flutter SDK'da IDFA, GAID veya reklam verisi toplanmaz." --- Flutter uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) ve [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla bu politikaları karşılayacak ve uygulama mağazası incelemelerinden geçecek şekilde yapılandırabilirsiniz. ## Ne yapılması gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdaki verilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [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 bir kullanıcı kimliği, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilir. Kids Mode için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (örneğin hash'lenmiş ID'ler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Kids Mode'u Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde yapılacak 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 kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için kullanıcının IDFA (iOS için), GAID/AAID (Android için) ve IP adresi toplamasını devre dışı bırakın. **Android: SDK yapılandırmanızı güncelleyin** ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') // highlight-start ..withGoogleAdvertisingIdCollectionDisabled(true) // set to `true` ..withIpAddressCollectionDisabled(true), // set to `true` // highlight-end ); } catch (e) { // handle the error } ``` **iOS: SDK v4'te Kids Mode'u Etkinleştirme** :::important SDK v4'te, yerel iOS SDK'sı Swift Package Manager aracılığıyla kurulur ve Kids Mode, IDFA, AdSupport ve AppTrackingTransparency kodlarının tamamını derlemeden çıkaran `KidsMode` Swift paket özelliği aracılığıyla etkinleştirilir. Bu, **Xcode 26** veya daha yeni bir sürüm gerektirir. ::: SDK v4'te, `pubspec.yaml` dosyanızda `adapty_flutter` yerine `adapty_flutter_kids` paketini kullanın. Bu, aynı genel API'ye ve aynı sürüme sahip, eklentinin Kids Mode varyantıdır — tek farkı, yerel iOS SDK'sının `KidsMode` özelliğiyle derlenmesidir: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter_kids: 4.0.0 ``` Dart kodunuz aynı kalır — yalnızca import'u yeni paket adıyla güncelleyin: ```dart showLineNumbers title="Dart" ``` **iOS: CocoaPods kullanarak Kids Mode'u etkinleştirme (SDK v3)** 1. Podfile dosyanızı güncelleyin: - `post_install` bölümünüz **yoksa**, aşağıdaki kod bloğunun tamamını ekleyin. - `post_install` bölümünüz **varsa**, vurgulanan satırları mevcut bölümle birleştirin. ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. Değişiklikleri uygulamak için şunu çalıştırın: ```sh showLineNumbers title="Shell" pod install ``` --- # File: flutter-get-onboardings --- --- title: "Flutter SDK'da onboarding'leri alma" description: "Flutter için Adapty'de onboarding'lerin nasıl alınacağını öğrenin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](flutter-get-pb-paywalls)'ları kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm ve his, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow'ları ve paywall'ları al](flutter-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüle](flutter-present-paywalls) sayfalarına bakın. ::: Adapty Kontrol Paneli'nde builder ile [onboarding'inizin görsel bölümünü tasarladıktan](design-onboarding) sonra, bunu Flutter uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır. Başlamadan önce şunları sağladığınızdan emin olun: 1. [Adapty Flutter SDK](sdk-installation-flutter) sürüm 3.8.0 veya daha yüksek bir sürümü yüklemiş olmalısınız. 2. [Bir onboarding oluşturmuş](create-onboarding) olmalısınız. 3. Onboarding'i bir [placement](placements)'a eklemiş olmalısınız. ## Onboarding'i getirme \{#fetch-onboarding\} No-code builder ile bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirip 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 (sınav yanıtları veya form girişleri gibi) nasıl işleneceğini belirler. Container ayrıca analitik etkinliklerini otomatik olarak takip eder, dolayısıyla ayrı bir görüntüleme takibi uygulamanıza gerek kalmaz. En iyi performans için, onboarding yapılandırmasını erken getirerek görsellerin kullanıcılara gösterilmeden önce indirilmesi için yeterli zaman tanıyın. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboarding(placementId: "YOUR_PLACEMENT_ID"); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` Ardından, göstereceğiniz görünümü almak için `createOnboardingView` metodunu çağırın. :::warning `createOnboardingView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `createOnboardingView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers try { final onboardingView = await Adapty().createOnboardingView(onboarding: onboarding); } on AdaptyError catch (e) { //handle error } catch (e) { //handle 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 etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.

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

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

SDK varsayılan olarak verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneririz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veriler mevcutsa bunları döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar düzensiz 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 sırasında güvenle kullanılabilir.

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

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

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

Bu değer, metodun zaman aşımını sınırlandırır. 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`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

| Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özelliklerle birlikte bir [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) nesnesi. | ## Varsayılan kitle onboarding'iyle onboarding getirmeyi hızlandırma \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir onboarding getirmek 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. Bu sorunu çözmek için `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz; bu metot, belirtilen placement'ın **All Users** kitlesi için onboarding'i getirir. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Getirme](#fetch-onboarding) bölümünde ayrıntılı olarak açıklandığı gibi `getOnboarding` metoduyla onboarding'i getirmek olduğunu anlamak son derece önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı değerlendirin; çünkü ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlara yol açabilir; ya geriye dönük uyumlu tasarımlar gerektirir ya da eski sürümlerin yanlış görüntülenebileceğini kabul etmek zorunda kalırsınız. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedeflemeyi kaldırır. Kullanım durumunuz için daha hızlı getirme bu dezavantajlardan daha önemliyse, aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown 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 etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.

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

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

SDK varsayılan olarak verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneririz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veriler mevcutsa bunları döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar düzensiz 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 sırasında güvenle kullanılabilir.

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

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

| --- # File: flutter-present-onboardings --- --- title: "Flutter SDK'da onboarding'leri gösterme" description: "Dönüşümleri artırmak için onboarding'leri etkili biçimde nasıl göstereceğinizi öğrenin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](flutter-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda doğrudan native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native 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ı edinin](flutter-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleyin](flutter-present-paywalls) sayfalarına bakın. ::: Builder ile bir onboarding oluşturduysanız, bunu Flutter uygulama kodunuzda kullanıcıya göstermek için ayrıca render etmeniz gerekmez. Bu tür bir onboarding, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. Başlamadan önce şunları kontrol edin: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 veya daha yeni bir sürümü yüklemiş olmanız. 2. Bir [onboarding oluşturmuş](create-onboarding) olmanız. 3. Onboarding'i bir [placement](placements)'a eklemiş olmanız. Adapty Flutter SDK, onboarding'leri sunmak için iki yöntem sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak göster \{#present-as-standalone-screen\} Bir onboarding'i bağımsız bir ekran olarak görüntülemek için, `createOnboardingView` metoduyla oluşturulan `onboardingView` üzerinde `onboardingView.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Onboarding'i tekrar göstermeniz gerekiyorsa, yeni bir `onboardingView` örneği oluşturmak için `createOnboardingView` metodunu bir kez daha çağırın. :::warning Aynı `onboardingView`'ı yeniden oluşturmadan tekrar kullanmak, `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Onboarding'i kapatma \{#dismiss-the-onboarding\} Onboarding'i programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine yerleştirme \{#embed-in-widget-hierarchy\} Bir onboarding'i mevcut widget ağacınıza gömmek için `AdaptyUIOnboardingPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Android platform view'ın çalışması için `MainActivity`'nizin `FlutterFragmentActivity`'yi genişlettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## Onboarding sırasında yükleme ekranı \{#loader-during-onboarding\} Bir onboarding sunarken, arka planda görünüm başlatılırken açılış ekranı ile onboarding arasında kısa bir yükleme ekranı görebilirsiniz. Bunu ihtiyacınıza göre farklı şekillerde ele alabilirsiniz. #### onDidFinishLoading kullanarak açılış ekranını kontrol etme \{#control-splash-screen-using-ondidfinishloading\} :::note Bu yaklaşım yalnızca onboarding bir widget olarak yerleştirildiğinde kullanılabilir. Bağımsız ekran sunumu için mevcut değildir. ::: Önerilen platformlar arası yaklaşım, onboarding tam olarak yüklenene kadar splash ekranını veya özel overlay'inizi görünür tutmak, ardından manuel olarak gizlemektir. Gömülü widget kullanırken, kendi widget'ınızı onun üzerine yerleştirin ve `onDidFinishLoading` tetiklendiğinde overlay'i gizleyin: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### Yerel yükleyiciyi özelleştirme \{#customize-native-loader\} :::important Bu yaklaşım platforma özgüdür ve yerel UI kodunun bakımını gerektirir. Uygulamanızda zaten ayrı yerel katmanlar kullanmıyorsanız önerilmez. ::: Varsayılan yükleyiciyi özelleştirmeniz gerekiyorsa platforma özgü layout'larla değiştirebilirsiniz. Bu yaklaşım Android ve iOS için ayrı uygulamalar gerektirir: - **iOS**: Xcode projenize `AdaptyOnboardingPlaceholderView.xib` ekleyin - **Android**: `res/layout` klasöründe `adapty_onboarding_placeholder_view.xml` oluşturun ve burada bir yer tutucu tanımlayın ## Onboarding'lerde bağlantıların nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboarding'lerde bağlantıların nasıl açılacağını özelleştirme özelliği Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboarding'lerdeki bağlantılar uygulama içi tarayıcıda açılır. Bu, web sayfalarını uygulamanızın içinde göstererek kullanıcıların başka bir uygulamaya geçmeden içeriği görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sunar. Bağlantıların bunun yerine harici tarayıcıda açılmasını tercih ediyorsanız, `externalUrlsPresentation` parametresini `AdaptyWebPresentation.externalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```dart showLineNumbers title="Flutter" final onboardingView = await AdaptyUI().createOnboardingView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser ); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` ## Güvenli alan dolgularını devre dışı bırakma (Android) \{#disable-safe-area-paddings-android\} Varsayılan olarak Android cihazlarda, onboarding görünümü durum çubuğu ve gezinme çubuğu gibi sistem UI öğelerinden kaçınmak için güvenli alan dolgularını otomatik olarak uygular. Ancak bu davranışı devre dışı bırakmak ve düzen üzerinde tam kontrol sahibi olmak istiyorsanız, uygulamanıza bir boolean kaynağı ekleyerek bunu yapabilirsiniz: 1. `android/app/src/main/res/values` konumuna gidin. `bools.xml` dosyası yoksa oluşturun. 2. Aşağıdaki kaynağı ekleyin: ```xml false ``` Bu değişikliklerin uygulamanızdaki tüm onboarding'ler için geçerli olduğunu unutmayın. --- # File: flutter-handling-onboarding-events --- --- title: "Flutter SDK'da onboarding olaylarını yönetme" description: "Flutter'da Adapty kullanarak onboarding ile ilgili olayları yönetin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](flutter-get-pb-paywalls)'ları kullanın: onboarding'lerin aksine WebView içinde çalışan onboarding'lerden farklı olarak, flow'lar cihazda doğal olarak render edilir — daha akıcı animasyonlar, tutarlı native görünüm ve his, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı olmadan kullanım sunar. Başlamak için [Flow ve paywall'ları al](flutter-get-pb-paywalls) ve [Flow ve paywall'ları göster](flutter-present-paywalls) sayfalarına bakın. ::: Builder ile yapılandırılmış onboarding'ler, uygulamanızın yanıt verebileceği olaylar oluşturur. Bu olayları nasıl işleyeceğiniz, kullandığınız sunum yöntemine bağlıdır: - **Tam ekran sunum**: Tüm onboarding görünümleri için olayları işleyen global bir olay gözlemcisi kurulmasını gerektirir - **Gömülü widget**: Olayları doğrudan widget içindeki satır içi geri çağırma parametreleri aracılığıyla işler Başlamadan önce şunlardan emin olun: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 veya daha yeni bir sürümü yüklediniz. 2. Bir [onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. ## Tam ekran sunum olayları \{#full-screen-presentation-events\} ### Olay gözlemcisini kurma \{#set-up-event-observer\} Tam ekran onboarding'ler için olayları işlemek üzere `AdaptyUIOnboardingsEventsObserver`'ı uygulayın ve sunmadan önce ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setOnboardingsEventsObserver(this); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Olayları işleme \{#handle-events\} Gözlemcinizde şu metodları uygulayın: ```dart showLineNumbers title="Flutter" void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { // Onboarding finished loading } void onboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error, ) { // Handle loading errors } void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle close action view.dismiss(); } void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle custom actions } void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle user input updates } void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { // Track analytics events } ``` ## Gömülü widget olayları \{#embedded-widget-events\} `AdaptyUIOnboardingPlatformView` kullanırken, olayları doğrudan widget içindeki satır içi callback parametreleri aracılığıyla işleyebilirsiniz. Olayların hem widget callback'lerine hem de global gözlemciye (ayarlandıysa) gönderileceğini, ancak global gözlemcinin isteğe bağlı olduğunu unutmayın: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Onboarding finished loading }, onDidFailWithError: (error) { // Handle loading errors }, onCloseAction: (meta, actionId) { // Handle close action }, onPaywallAction: (meta, actionId) { _openPaywall(actionId); }, onCustomAction: (meta, actionId) { // Handle custom actions }, onStateUpdatedAction: (meta, elementId, params) { // Handle user input updates }, onAnalyticsEvent: (meta, event) { // Track analytics events }, ) ``` ## Olay türleri \{#event-types\} Aşağıdaki bölümler, hangi sunum yaklaşımını kullandığınızdan bağımsız olarak işleyebileceğiniz farklı olay türlerini açıklamaktadır. ### Özel eylemleri işleme \{#handle-custom-actions\} Builder'da bir butona **custom** eylem ekleyip ona 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 butona dokunduğunda, `onboardingController` delegate metodu `.custom(id:)` durumuyla tetiklenecek ve `actionId` parametresi builder'daki **Action ID** olacaktır. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```dart // Full-screen presentation void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { switch (actionId) { case 'login': _login(); break; case 'allow_notifications': _allowNotifications(); break; } } // Embedded widget onCustomAction: (meta, actionId) { _handleCustomAction(actionId); } ```
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 yüklemesini tamamlama \{#finishing-loading-onboarding\} Bir onboarding yüklemeyi tamamladığında şu olay tetiklenecektir: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { print('Onboarding loaded: ${meta.onboardingId}'); } // Embedded widget onDidFinishLoading: (meta) { print('Onboarding loaded: ${meta.onboardingId}'); } ```
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 } } ```
### Onboarding'i kapatma \{#closing-onboarding\} Bir kullanıcı **Close** eylemi atanmış bir butona dokunduğunda onboarding kapatılmış sayılır. :::important Bir kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini görüntülemeyi durdurmanız gerekir. ::: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { await view.dismiss(); } // Embedded widget onCloseAction: (meta, actionId) { Navigator.of(context).pop(); } ```
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 } } ```
### Bir paywall açma \{#opening-a-paywall\} :::tip Bu etkinliği, onboarding içinde bir paywall açmak istiyorsanız işleyin. Eğer paywall kapandıktan sonra açmak istiyorsanız, bunu yapmanın daha doğrudan bir yolu var: kapatma eylemini işleyin ve etkinlik verilerine dayanmadan bir paywall açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, eylem ID'sini bir paywall placement ID'siyle eşit yapmaktır: iOS'ta ekranda aynı anda yalnızca bir görünüm (paywall veya onboarding) görüntülenebilir. Onboarding'in üzerine bir paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışmak paywall'ı kapatacak ve onboarding görünür kalacaktır. Bunu önlemek için, her zaman paywall'ı sunmadan önce onboarding görünümünü kapatın. ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } Future _openPaywall(String actionId) async { // Implement your paywall opening logic here } // Embedded widget onPaywallAction: (meta, actionId) { _openPaywall(actionId); } ```
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 } } ```
### Navigasyonu izleme \{#tracking-navigation\} Onboarding akışı sırasında çeşitli navigasyon ile ilgili olaylar gerçekleştiğinde bir analitik olayı alırsınız: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { trackEvent(event.type, meta.onboardingId); } // Embedded widget onAnalyticsEvent: (meta, event) { trackEvent(event.type, meta.onboardingId); } ``` `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ıdan gelen 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-postası giriş alanı aracılığıyla toplandığında tetiklenir | | `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa, [son ekrana `final` ID'sini atayın](design-onboarding). | | `unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veri) içerir | Her olay şunu içeren `meta` bilgisini barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Mevcut ekranın akıştaki konumu | | `screensTotal` | Akıştaki toplam ekran sayısı |
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: flutter-onboarding-input --- --- title: "Flutter SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Flutter uygulamanızda onboarding verilerini kaydedin ve kullanın." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmış olup gelecekteki bir sürümde tamamen kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](flutter-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall'ları edinme](flutter-get-pb-paywalls) ve [Flow ve paywall'ları görüntüleme](flutter-present-paywalls) bölümlerine bakın. ::: Kullanıcılarınız bir sınav 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: ```dart // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Process data } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Process data } ``` Buradaki action formatına [bakın](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyUIOnboardingPlatformView/onStateUpdatedAction.html).
Her params türü için property şekilleri (genişletmek için tıklayın) ```dart void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // elementId is a String: elementId; // 'preference_selector' // meta — AdaptyUIOnboardingMeta: meta.onboardingId; // 'onboarding_123' meta.screenClientId; // 'preferences_screen' meta.screenIndex; // 1 meta.screensTotal; // 3 // params is one of the AdaptyOnboardingsStateUpdatedParams subclasses: switch (params) { case AdaptyOnboardingsSelectParams(:final id, :final value, :final label): // a single selected option id; // 'option_1' value; // 'premium' label; // 'Premium Plan' break; case AdaptyOnboardingsMultiSelectParams(:final params): // a list of selected options, each an AdaptyOnboardingsSelectParams params; // [(id: 'interest_1', value: 'sports', label: 'Sports'), (id: 'interest_2', value: 'music', label: 'Music')] break; case AdaptyOnboardingsInputParams(:final input): switch (input) { case AdaptyOnboardingsTextInput(:final value): value; // 'John Doe' break; case AdaptyOnboardingsEmailInput(:final value): value; // 'user@example.com' break; case AdaptyOnboardingsNumberInput(:final value): value; // 25.0 (a double) break; } break; case AdaptyOnboardingsDatePickerParams(:final day, :final month, :final year): day; // 15 month; // 6 year; // 1990 break; } } ```
## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle anında ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](flutter-setting-user-attributes) girilen verilerle güncellemeniz 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 kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta girmelerini istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```dart showLineNumbers // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` ### Yanıtlara göre paywall'ları özelleştirme \{#customize-paywalls-based-on-answers\} Onboarding'lerde quiz kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywall'ları da özelleştirebilirsiniz. Örneğin, kullanıcılara spor deneyimleri hakkında sorular sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding oluşturucusuna [bir quiz ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler ayarlayın](flutter-setting-user-attributes). ```dart showLineNumbers // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // 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 placement için bir [paywall görüntüleyin](flutter-paywalls). Onboarding'inizde bir paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](flutter-handling-onboarding-events#opening-a-paywall) olarak uygulayın. --- # File: flutter-sdk-call-order --- --- title: "Flutter SDK'da çağrı sırası" description: "Adapty SDK metotlarını doğru sırayla çağırarak kayıp premium erişim, eksik attribution ve aralıklı #2002 hatalarından kaçının." --- `Adapty().activate()` tamamlanmadan diğer hiçbir Adapty SDK metodunu çağıramazsınız. Bu metot çözümlenmeden SDK'nın herhangi bir durumu yoktur. `activate()` ile eş zamanlı ya da daha önce yapılan tüm çağrılar [`#2002 notActivated`](error-handling-on-flutter-react-native-unity#custom-network-codes) hatasıyla sonuçlanır. Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, bu noktada `Adapty().identify()` çağrısını yapın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metotları çağırmayın. Bununla yarışan çağrılar ya [`#3006 profileWasChanged`](error-handling-on-flutter-react-native-unity#custom-network-codes) hatasıyla başarısız olur ya da etkinleştirme sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP kimlikleri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları 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. `Adapty().activate` çağrısından önce bunları başlatın ve UID geri çağırımlarını bekleyin. Aksi takdirde MMP kimliği, kısa ömürlü anonim bir profile düşer ve tanımlı profile her zaman aktarılmaz. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıra \{#the-correct-order\} Hangi adımları izleyeceğiniz 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şlatıldığında müşteri kullanıcı kimliğiniz elinizde varsa, bunu doğrudan `activate()` fonksiyonuna geçirin (adım 2a). Bu yöntem hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gereksizdir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama açılışı, ilk önce | MMP'nin UID callback'ini bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `withCustomerUserId` yapılandırmada ayarlanmış şekilde `Adapty().activate(configuration: ...)` | Uygulama açılışı, 1. adımdan sonra, customer user ID'niz varsa | Önerilen. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `withCustomerUserId` olmadan `Adapty().activate(configuration: ...)` | Uygulama açılışı, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty().setIntegrationIdentifier(key: ..., value: ...)` | 2. adımdan sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için gereklidir. | | 4 | `await Adapty().identify(customerUserId)` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulama ile 2b yolunda | Her zaman `await` kullanın. `identify` sırasında eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar. | | 5 | `getPaywall` (SDK v4'te `getFlow`), `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi takdirde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::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 yüklemeleri \{#web2app-and-web-funnel-installs\} Kullanıcılar web üzerinden ödeme yapıp (Stripe, Paddle) sonradan uygulamayı yüklerse, cihazda ilk çalışan `activate()` yeni bir anonim profil oluşturur. Bu profil, web profiline bağlı değildir. Uygulama açılmadan önce müşteri kullanıcı kimliğini belirleyebiliyorsanız (auth akışınızdan veya install referrer üzerinden), bunu doğrudan `activate()` içine geçirin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` çağrısı yapıp ardından `restorePurchases` çağırana kadar cihazda görünmez. Her web ödemesiyle gönderilecek metadata için şu sayfalara bakabilirsiniz: - [Stripe](stripe) - [Paddle](paddle) --- # File: flutter-optimize-paywall-fetching --- --- title: "Flutter SDK'da paywall çekme işlemini optimize edin" description: "Adapty paywalllarını güvenilir şekilde çekin: Flutter için zamanlama, önbellekleme ve yedek kalıplar." --- Flutter'da güvenilir bir paywall çekme işlemi üç şey yapar: hızlı render eder, kitleye özel paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz bir şekilde yedek davranışa geçer. Aşağıdaki kurallar bunu başarmanın zamanlama, önbellekleme ve yedek kalıplarını kapsar. :::tip Aşağıdaki kurallar, `Adapty().activate()` ve `Adapty().identify()` işlevlerinin zaten tamamlandığını varsayar. Daha fazla bilgi için bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ::: Aşağıdaki tavsiyeler v3 metot adlarını kullanmaktadır. SDK v4'te `getPaywall`, `getFlow` olarak; fetch policy türü ise `AdaptyFlowFetchPolicy` olarak yeniden adlandırılmıştır — tüm kurallar değişmeden geçerlidir. ## Kurallar ve dikkat edilmesi gereken noktalar \{#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 önceden getirme işlemi ana iş parçacığını engeller ve yoğunluk sırasında siyah ekrana yol açar. | | `getPaywall`'ı attribution'ın çözülmesine fırsat verdikten sonra çağırın — örneğin `activate`'den 1–2 saniye sonra veya `didUpdateProfileStream` tetiklendikten sonra. | `getPaywall`'ı `runApp`'ten önce `main()` 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` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ı süresiz olarak bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf kullanıcılar ağ çözümlenene kadar boş ekran görür ya da uygulamayı kapatır. | [Paywall ve ürünleri getirme](fetch-paywalls-and-products-flutter) sayfasında `fetchPolicy` ve `loadTimeout` parametre referanslarına, [Placement'lar](placements) sayfasında ise doğru placement'ı seçmeye ilişkin bilgilere ulaşabilirsiniz. ## Kötü bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli kötü bağlantı yaşanan pazarlar için (kırsal alanlar, ulaşım güzergahları, yönlendirme sorunlarından etkilenen bölgeler): - İlk fetch dışında her fetch işleminde `fetchPolicy: AdaptyPaywallFetchPolicy.returnCacheDataElseLoad` kullanın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniyeye ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin. - Paywall görüntülemeyi `getProfile()` yanıtına bağlamayın. Yavaş bir profilin arayüzü bloke etmemesi için `getPaywall` işlemini bağımsız olarak çağırın. --- # File: flutter-show-aa-targeted-paywall --- --- title: "Flutter SDK'da ilk açılışta AA hedefli paywall gösterme" description: "Flutter'da ilk açılışta paywall göstermeden önce Apple Ads attribution verisini kısa süre bekleyin; zaman aşımında varsayılan kitleye geri dönün. AdaptyProfile.appliedAttributionSources kullanır." --- Apple Ads (AA) attribution, `Adapty().activate()` çağrısından sonra asenkron olarak gelir. İlk açılışta genellikle henüz gelmemiş olduğundan, hemen `getPaywall` çağırırsanız Adapty isteği varsayılan kitleye göre çözümler ve Apple Ads kullanıcıları AA segmentine özel paywallunuzu göremez. Bir paywallı gösterip sonra değiştirmek yerine, herhangi bir şey göstermeden önce AA attribution'ının gelmesini kısaca bekleyin: attribution kısa bir zaman aşımı içinde gelirse hedeflenmiş paywallı, gelmezse varsayılan kitle paywallını gösterin. `AdaptyProfile.appliedAttributionSources`, AA attribution'ının uygulanıp uygulanmadığını size bildirir. ## Başlamadan önce \{#before-you-start\} İhtiyacınız olanlar: - Adapty Flutter SDK **3.17.0** veya üzeri. - Adapty'de uygulama için yapılandırılmış Apple Ads. Bkz. [Apple Ads](apple-search-ads). ## Nasıl çalışır \{#how-it-works\} `Adapty().activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution verilerini ister ve sonucu Adapty'nin backend'ine iletir. AA, profil için aktif attribution kaynağı haline geldiğinde SDK, `didUpdateProfileStream` dinleyicinize güncellenmiş bir `AdaptyProfile` iletir; bu profil, `appliedAttributionSources` listesinde `AdaptyAttributionSource.appleAds` değerini içerir. İlk başlatmada ele almanız gereken iki olası sonuç vardır: 1. **Attribution zaman aşımı süreniz içinde gelir.** `getPaywall` çağrısı yapın — Adapty isteği Apple Ads kitlesine göre çözümler ve hedeflenmiş paywall'ı döndürür. 2. **Önce zaman aşımı süresi dolar.** Bunun yerine varsayılan kitle paywall'ını gösterin; böylece Apple Ads attribution'ı olmayan kullanıcılar beklemek zorunda kalmaz. `getPaywallForDefaultAudience`, segmentasyon için beklemeden bunu döndürür. `appliedAttributionSources` boş olabilir. Bu şu anlama gelir: - Bu profil için Apple Ads attribution'ı henüz işlenmemiştir veya - hiç attribution gelmemiştir. Her iki durumda da `getPaywallForDefaultAudience` güvenle çağrılabilir — profil durumundan bağımsız olarak varsayılan kitleye ait paywall'ı döndürür. :::important Bekleme yalnızca ilk başlatma için geçerlidir. Apple Ads attribution'ı bir kez kaydedildikten sonra, profilde kalıcı olarak saklanır. Sonraki her başlatmada, önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `AdaptyAttributionSource.appleAds` bilgisini taşır; bu sayede attribution yolu hemen çözümlenir ve `getPaywall` herhangi bir gecikme olmadan Apple Ads segmentine göre paywall'ı döndürür. ::: ## Uygulama \{#implementation\} İlk başlatmada `AdaptyAttributionSource.appleAds` için bekleyin ve katı bir zaman aşımı uygulayın — Apple Ads attribution hiç gelmese de, bu kullanıcıların yine de bir paywall görmesi gerekir. 1. **SDK'yı etkinleştirin.** Bkz. [Flutter SDK'yı yükle ve yapılandır](sdk-installation-flutter). 2. **`Adapty().didUpdateProfileStream.listen(…)` ile profil güncellemelerini dinleyin.** Henüz dinleyiciyi kurmadıysanız bkz. [Abonelik güncellemelerini dinle](flutter-check-subscription-status#listen-to-subscription-updates). 3. **`appliedAttributionSources` içinde `AdaptyAttributionSource.appleAds` değerini bekleyin.** Bu değer göründüğünde `getPaywall` ile paywallı yükleyin — Adapty, AA segmentine uygun varyantı döndürür: ```dart final subscription = Adapty().didUpdateProfileStream.listen((profile) async { if (!profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) return; final paywall = await Adapty().getPaywall(placementId: placementId); // segmentlenmiş paywall'u göster, ardından aboneliği ve zamanlayıcıyı iptal et }); ``` `didUpdateProfileStream` bir broadcast stream'dir ve yeniden oynatma yapmaz; bu nedenle `getProfile()` ile mevcut profili bir kez de doğrudan kontrol edin. Uygulama yeniden başlatıldığında, kaydedilmiş attribution zaten uygulanmış olur ve yeniden emit edilmez. 4. **Abonelikle paralel olarak 3–5 saniyelik bir zamanlayıcı başlatın.** Zamanlayıcı, `AdaptyAttributionSource.appleAds` gelmeden önce tetiklenirse, bunun yerine `getPaywallForDefaultAudience` ile varsayılan kitle paywallını yükleyin. Önce çözümlenen paywallı gösterin ve diğer yolu iptal edin; böylece paywall iki kez çekilmez. Ağ isteği başarısız olursa kullanıcının askıda kalmaması için placement'a bir [yedek paywall](flutter-use-fallback-paywalls) yapılandırın. ## Tam örnek \{#complete-example\} Aşağıdaki uygulama, attribution'ı bir zaman aşımıyla yarıştırır, varsayılan kitle paywall'ını paralelde önceden yükler ve uygun olan paywall'ı döndürür. Çağıran taraf yalnızca tek bir fonksiyonu bekler — çağrı noktasında yönetilecek dinleyici veya durum bayrağı yoktur: - Attribution `timeout` süresi içinde gelirse, `getPaywall` aracılığıyla segmentlere ayrılmış paywall'ı döndürür. - Önce `timeout` süresi dolarsa, `getPaywallForDefaultAudience` aracılığıyla önceden yüklenmiş varsayılan kitle paywall'ını döndürür. ```dart title="apple_ads_paywall.dart" /// Returns the Apple Ads-segmented paywall if attribution is applied within /// [timeout], otherwise the default-audience paywall. Call after Adapty().activate(). Future getPaywallOrDefault({ required String placementId, required Duration timeout, }) { // Prefetch the default-audience paywall right away so the timeout path resolves // without an extra network round-trip. `getPaywallForDefaultAudience` skips the // wait for segmentation data. `..ignore()` keeps an unused prefetch from surfacing // as an unhandled error; the error still reaches the caller if this paywall wins. final defaultPaywall = Adapty().getPaywallForDefaultAudience(placementId: placementId)..ignore(); final completer = Completer(); late final StreamSubscription subscription; late final Timer timer; void resolve(Future paywall) { if (completer.isCompleted) return; timer.cancel(); subscription.cancel(); completer.complete(paywall); } void onProfile(AdaptyProfile profile) { if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) { resolve(Adapty().getPaywall(placementId: placementId)); } } // Attribution path: react to profile updates as attribution is applied. subscription = Adapty().didUpdateProfileStream.listen(onProfile); // The stream is a broadcast stream and doesn't replay, so check the current // profile too — on relaunches attribution is already stored and won't re-emit. Adapty().getProfile().then(onProfile).ignore(); // Timeout path: fall back to the prefetched default-audience paywall. timer = Timer(timeout, () => resolve(defaultPaywall)); return completer.future; } ``` Splash ekranınızdan çağırın, ardından tamamlandığında paywallı gösterin: ```dart try { final paywall = await getPaywallOrDefault( placementId: 'YOUR_PLACEMENT_ID', timeout: const Duration(seconds: 5), ); // present the paywall } on AdaptyError catch (adaptyError) { // handle the error or show a fallback paywall } catch (e) { // handle the error } ``` `timeout` değerini, kullanıcılarınızı herhangi bir paywall görünmeden önce ne kadar bekletmek istediğinize göre ayarlayın. Kullanıcıların büyük çoğunluğunun Apple Ads attribution verisi olmadığını düşünürsek, hepsi tam timeout süresini bekler; bu yüzden 3 ila 5 saniye makul bir denge noktasıdır. Gelmesi beklenen attribution verisi genellikle uygulama açılışından birkaç saniye içinde ulaşır. Uygulamanız başka amaçlarla (örneğin, [abonelik durumunu kontrol etmek](flutter-check-subscription-status#listen-to-subscription-updates) için) zaten `didUpdateProfileStream`'i dinliyorsa, herhangi bir değişiklik yapmanıza gerek yok. `didUpdateProfileStream` bir broadcast stream olduğundan, birbirinden bağımsız birden fazla dinleyiciyi destekler ve bunları birbirini etkilemeden kullanabilirsiniz. --- # File: flutter-test --- --- title: "Flutter SDK'da test etme ve yayınlama" description: "Adapty ile Flutter uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Flutter uygulamanıza Adapty SDK'yı zaten entegre ettiyseniz, her şeyin doğru şekilde kurulduğunu ve satın almaların hem iOS hem de Android platformlarında beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de Apple'ın sandbox ortamı ve Google Play'in test ortamıyla gerçek satın alma akışını test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almaları kapsamlı şekilde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayına hazırlanma \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesi](release-checklist)'ni takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'ye bildiriliyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanmış --- # File: InvalidProductIdentifiers-flutter --- --- title: "Flutter SDK'da Code-1000 noProductIDsFound Hatası İçin Çözüm" description: "Adapty'de abonelikleri yönetirken oluşan geçersiz ürün tanımlayıcısı hatalarını çözün." --- 1000 kodlu hata olan `noProductIDsFound`, paywall'da talep ettiğiniz ürünlerin App Store'da listelenmesine rağmen satın alma için mevcut olmadığını gösterir. Bu hata bazen `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız görünüyorsa güvenle yok sayabilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız çözmek için aşağıdaki adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin \{#step-3-check-products\} 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne gidin. 2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümünün altında listelenmiş olarak göreceksiniz. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. 4. Tablodaki ürün ID'sini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesiyle karşılaştırın. ID'ler eşleşmiyorsa ürün ID'sini tablodan kopyalayıp Adapty Kontrol Paneli'nde bu ID ile [bir ürün oluşturun](create-product). ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. 2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. 4. **Availability** bölümüne kaydırın ve gereken tüm ülke ve bölgelerin listelendiğini doğrulayın. ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'te **Monetization** → **Subscriptions** bölümüne tekrar gidin. 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. 4. **Subscription Pricing** bölümüne kaydırın ve **Current Pricing for New Subscribers** bölümünü genişletin. 5. Gerekli tüm fiyatların listelendiğinden emin olun. ## Adım 5. Uygulamanın ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) ana sayfasında **Business**'a tıklayın. 2. Şirketinizin adını seçin. 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** bölümlerinin hepsinin **Active** olarak göründüğünü doğrulayın. Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayına alabilirsiniz. ## Adım 6. Takılı kaldıysa ürünü yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5. adımların hepsi geçiyor olabilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — ama SDK yine de `1000 noProductIDsFound` döndürüyor olabilir. Bu durumda ürün Apple'ın kayıt defterinde takılı kalmış olabilir. Apple'ın ürün kayıt defteri zaman zaman bir ürünün App Store Connect arayüzünde var olduğu ancak StoreKit arama yoluna açık olmadığı bir duruma girebilir. Ürünü App Store Connect'te silin ve aynı ürün ID'siyle yeniden oluşturun. Yayılma için yeniden oluşturulduktan sonra 24 saate kadar bekleyin. --- # File: cantMakePayments-flutter --- --- title: "Flutter SDK'da Code-1003 cantMakePayment hatasının çözümü" description: "Adapty'de abonelikleri yönetirken ödeme yapma hatasını çözün." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: migration-to-flutter-sdk-v4 --- --- title: "Adapty Flutter SDK'yı v. 4.0'a Geçirin" description: "Adapty Flutter 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 Flutter 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ı başvuru \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty().getPaywall(placementId: id)` | `Adapty().getFlow(placementId: id)` | | `Adapty().getPaywallForDefaultAudience(placementId: id)` | `Adapty().getFlowForDefaultAudience(placementId: id)` | | `Adapty().getPaywallProducts(paywall: paywall)` | `Adapty().getPaywallProducts(flow: flow)` | | `Adapty().logShowPaywall(paywall: paywall)` | `Adapty().logShowFlow(flow: flow)` | | `AdaptyPaywall` (tür) | `AdaptyFlow` | | `AdaptyPaywallFetchPolicy` (tür) | `AdaptyFlowFetchPolicy` | | `AdaptyUI().createPaywallView(paywall: paywall)` | `AdaptyUI().createFlowView(flow: flow)` | | `AdaptyUIPaywallView` (tür) | `AdaptyUIFlowView` | | `AdaptyUIPaywallPlatformView` (widget) | `AdaptyUIFlowPlatformView` | | `AdaptyUI().presentPaywallView(view)` / `dismissPaywallView(view)` | `AdaptyUI().presentFlowView(view)` / `dismissFlowView(view)` | | `AdaptyUIPaywallsEventsObserver` | `AdaptyUIFlowsEventsObserver` | | `AdaptyUI().setPaywallsEventsObserver(observer)` | `AdaptyUI().setFlowsEventsObserver(observer)` | | `paywallViewDid*` callback'leri | `flowViewDid*` callback'leri | | `paywallViewDidFailRendering` | `flowViewDidReceiveError` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` artık bir `AdaptyFlow` alır. Bir flow çekerken artık `locale` geçirmenize gerek yoktur. Satın alma ve profil API'leri (`makePurchase`, `restorePurchases`, `getProfile`, `identify` vb.) değişmeden kalmıştır; `present`, `dismiss` ve `showDialog` view metodları da aynı şekilde. Bazı varsayılan davranışlar değişti — bkz. [Varsayılan davranış değişiklikleri](#default-behavior-changes). ## Minimum sürümler \{#minimum-versions\} Adapty Flutter SDK 4.0, minimum gereksinimleri yükseltiyor: - **iOS 15.0** — minimum iOS deployment target, iOS 13.0'dan yükseltildi. - **Xcode 26** veya daha yenisi — yerel iOS SDK'sı Swift tools 6.2 kullanıyor. - **Flutter 3.32.0** (Dart 3.8.0) veya daha yenisi. ## Kurulum \{#installation\} ### Paketi güncelleyin \{#update-the-package\} Hangi paketi yükleyeceğiniz, uygulamanızın Kids Mode kullanıp kullanmadığına bağlıdır. Çoğu uygulama için `pubspec.yaml` dosyanızda `adapty_flutter` paketini v4.0'a güncelleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: 4.0.0 ``` Uygulamanız Kids Mode kullanıyorsa bunun yerine `adapty_flutter_kids` belirtin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter_kids: 4.0.0 ``` Bu **bağımsız** paket, App Store gereksinimlerine uymak için IDFA ve reklam takip kodlarını kaldırır. Dart import yolunu `package:adapty_flutter_kids/adapty_flutter.dart` olarak güncelleyin. Bunun dışında, migration işlemi normal paketle tamamen aynıdır. Kids Mode ayrıca Adapty Kontrol Paneli'nde IP adresi toplamanın devre dışı bırakılmasını gerektirir — tam kurulum için [Kids Mode](kids-mode-flutter) sayfasına bakın. ### iOS: yerel SDK'lar artık Swift Package Manager üzerinden geliyor \{#ios-native-sdks-now-come-through-swift-package-manager\} [CocoaPods'ın spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), bu nedenle v4 itibarıyla yerel iOS SDK'sı **artık CocoaPods üzerinden dağıtılmıyor** — eklenti bunu yalnızca **Swift Package Manager** aracılığıyla çekiyor. Flutter 3.32–3.43 kullanıyorsanız, Swift Package Manager desteğini bir kez etkinleştirin: ```bash flutter config --enable-swift-package-manager ``` Flutter 3.44 ve sonrası Swift Package Manager'ı varsayılan olarak etkinleştiriyor, dolayısıyla bu sürümlerde herhangi bir işlem yapmanıza gerek yok. ## Flow'ları getirme \{#fetching-flows\} ### getPaywall → getFlow Dönen tür `AdaptyPaywall` yerine `AdaptyFlow` olarak değişti ve artık `locale` parametresi geçmiyorsunuz — bir flow render ettiğinizde yerelleştirme otomatik olarak çözümlenir; özel paywalllar için yapılandırılmış tüm locale'lar `flow.remoteConfigs` içinde döner: ```diff showLineNumbers - final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID', locale: 'en'); + final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); ``` `getPaywallForDefaultAudience` da aynı şekilde yeniden adlandırıldı: ```diff showLineNumbers - final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID', locale: 'en'); + final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); ``` Fetch policy türü `AdaptyPaywallFetchPolicy`'den `AdaptyFlowFetchPolicy`'ye yeniden adlandırıldı; seçenekleri (`reloadRevalidatingCacheData`, `returnCacheDataElseLoad`, `returnCacheDataIfNotExpiredElseLoad`) değişmedi. ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` adını korur ancak artık `flow` parametresi aracılığıyla bir `AdaptyFlow` alır: ```diff showLineNumbers - final products = await Adapty().getPaywallProducts(paywall: paywall); + final products = await Adapty().getPaywallProducts(flow: flow); ``` ## Veri modeli \{#data-model\} `getFlow`, `AdaptyPaywall` yerine bir `AdaptyFlow` döndürür ve nesne yapısı değişti: | v3 `AdaptyPaywall` üyesi | v4 `AdaptyFlow` üyesi | İşlem | |---|---|---| | `remoteConfig` (tekil, nullable) | `remoteConfigs` (liste) | Bir flow, yapılandırılmış her dil için bir remote config taşır. `remoteConfig` getter'ı hâlâ mevcuttur ve ilk girişi döndürür; belirli bir dil seçmek için `remoteConfigs` içinde `locale` değerine göre arama yapın. | | `productIdentifiers` | `productIdentifiers` | Korundu, ancak artık flow'un tüm paywall varyasyonlarından derleniyor. Varyasyon bazındaki tanımlayıcılar `flow.paywalls[i].productIdentifiers` üzerinde bulunur. | | `hasViewConfiguration` | `hasViewConfiguration` | Değişmedi. | | `placementId` (kullanımdan kalktı) | kaldırıldı | `flow.placement.id` kullanın. | | `revision` (kullanımdan kalktı) | kaldırıldı | `flow.placement.revision` kullanın. | | `vendorProductIds` (kullanımdan kalktı) | kaldırıldı | `productIdentifiers` kullanın. | | _(yeni)_ | `paywalls` (`AdaptyFlowPaywall` listesi) | Her giriş, flow içindeki bir paywall varyasyonunu temsil eder ve kendine ait `name`, `variationId` ve `productIdentifiers` değerlerine sahiptir. | `AdaptyPaywallViewConfiguration` artık açık değil — görünüm yapılandırması artık opak. Bu türe yapılan tüm referansları kaldırın. ## Web paywall metodları \{#web-paywall-methods\} `openWebPaywall` ve `createWebPaywallUrl` isimlerini korur, ancak `paywall` parametresi artık `AdaptyPaywall` yerine `AdaptyFlowPaywall` (bir flow varyasyonu) alır. Yine de bunun yerine `AdaptyPaywallProduct` geçirebilirsiniz. ```diff showLineNumbers final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); - await Adapty().openWebPaywall(paywall: paywall); + if (flow.paywalls.isNotEmpty) { + await Adapty().openWebPaywall(paywall: flow.paywalls[0]); + } ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık bir `AdaptyFlow` alıyor. Olay aynı varyasyon üzerinden kaydedilmeye devam eder; bu sayede mevcut funnel ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapmadan çalışmayı sürdürür. ```diff showLineNumbers - await Adapty().logShowPaywall(paywall: paywall); + await Adapty().logShowFlow(flow: 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\} ### createPaywallView → createFlowView Metodu yeniden adlandırın ve `AdaptyFlow`'u `flow` parametresi aracılığıyla geçirin. Diğer parametreler (`loadTimeout`, `preloadProducts`, `customTags`, `customTimers`, `customAssets`, `productPurchaseParams`) ve view metodları `present`, `dismiss` ve `showDialog` değişmeden kalır: ```diff showLineNumbers - final view = await AdaptyUI().createPaywallView(paywall: paywall); + final view = await AdaptyUI().createFlowView(flow: flow); await view.present(); ``` ### AdaptyUIPaywallView → AdaptyUIFlowView Görünüm türü yeniden adlandırıldı. Kullanımdan kaldırılmış `paywallVariationId` özelliği kaldırıldı — bunun yerine `variationId` kullanın: ```diff showLineNumbers - void flowViewDidAppear(AdaptyUIPaywallView view) { + void flowViewDidAppear(AdaptyUIFlowView view) { ``` ### AdaptyUIPaywallPlatformView → AdaptyUIFlowPlatformView Görünümü widget ağacınıza widget olarak gömmek istiyorsanız, adını değiştirin ve `flow` parametresini geçin. Olay callback'leri (`onDidAppear`, `onDidFinishPurchase` vb.) aynı isimlerini korur: ```diff showLineNumbers - AdaptyUIPaywallPlatformView( - paywall: paywall, + AdaptyUIFlowPlatformView( + flow: flow, onDidFinishPurchase: (view, product, purchaseResult) { /* … */ }, ) ``` :::note `createFlowView` ile oluşturulan bir flow görünümü tek kullanımlıktır: `dismiss()` çağrıldıktan sonra görünüm bellekten serbest bırakılır ve bir daha gösterilemez — flow'u tekrar göstermek için `createFlowView`'ı yeniden çağırın. ::: ## Olayları Yönetme \{#handling-events\} Observer sınıfı `AdaptyUIPaywallsEventsObserver`'dan `AdaptyUIFlowsEventsObserver`'a, kayıt metodu `setPaywallsEventsObserver`'dan `setFlowsEventsObserver`'a ve tüm `paywallViewDid*` callback'leri `flowViewDid*`'e yeniden adlandırıldı: ```diff showLineNumbers - class MyObserver extends AdaptyUIPaywallsEventsObserver { + class MyObserver extends AdaptyUIFlowsEventsObserver { @override - void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { + void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { // … } } - AdaptyUI().setPaywallsEventsObserver(this); + AdaptyUI().setFlowsEventsObserver(this); ``` Artık üç callback **zorunludur** — bunlar olmadan observer'ınız derlenmez: - **`flowViewDidFinishPurchase`**: v3'te isteğe bağlıydı; varsayılan davranış satın alma sonrasında görünümü kapatıyordu. Artık ne olacağına siz karar veriyorsunuz: flow'a devam edin ya da `view.dismiss()` çağırın. - **`flowViewDidFinishRestore`**: v3'te olduğu gibi zorunludur. - **`flowViewDidReceiveError`**: `paywallViewDidFailRendering` yerine gelir ve artık diğer görünüm hatalarını da alır. İki küçük değişiklik daha: - `setFlowsEventsObserver` (ve `setOnboardingsEventsObserver`) artık önceden ayarlanmış bir observer'ı ayırmak için `null` kabul ediyor; bu sayede SDK artık onu tutmuyor. - Yeni isteğe bağlı `flowViewDidReceiveAnalyticEvent` callback'i, bir flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmiyor, dolayısıyla bunu uygulamanız gerekmiyor. v4 ayrıca isteğe bağlı olarak kullanabileceğiniz yeni özellikler ekliyor: - `AdaptyUI().setObserverModeResolver(...)` ile birlikte `AdaptyUIObserverModeResolver` — SDK [Observer mode](implement-observer-mode-flutter) olarak çalışırken flow'lardan başlatılan satın alma ve geri yüklemeleri yönetir. Daha önce bu yalnızca native iOS ve Android SDK'larında kullanılabiliyordu. Bkz. [Flow'ları Observer mode'da sunma](flutter-present-flows-in-observer-mode). - `AdaptyUI().setSystemRequestsHandler(...)` ile birlikte `AdaptyUISystemRequestsHandler` — bir flow'dan gelen sistem istekleri (işletim sistemi izin istemleri ve App Store inceleme istekleri) için ayrılmıştır. Flow'lar henüz bu istekleri tetiklemediğinden bir handler kaydetmeniz gerekmez. ## Kaldırılan API'lar \{#removed-apis\} Bu semboller 3.x sürümünde kullanımdan kaldırılmıştı ve v4'te tamamen kaldırılmıştır: ### setFallbackPaywalls → setFallback ```diff showLineNumbers - await Adapty().setFallbackPaywalls(assetId); + await Adapty().setFallback(assetId); ``` ### withIdfaCollectionDisabled → withAppleIdfaCollectionDisabled ```diff showLineNumbers configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') - ..withIdfaCollectionDisabled(true), + ..withAppleIdfaCollectionDisabled(true), ``` ### Kaldırılan diğer üyeler \{#other-removed-members\} - **`AdaptyPurchaseResultSuccess.jwsTransaction`**: `appleJwsTransaction` kullanın. - **`AdaptyUIFlowView.paywallVariationId`**: `variationId` kullanın. - **`AdaptyUIObserver` ve `AdaptyUI().setObserver(...)`**: `AdaptyUIFlowsEventsObserver` ve `setFlowsEventsObserver(...)` kullanın. ## Varsayılan davranış değişiklikleri \{#default-behavior-changes\} Bu değişiklikler derleme hatası oluşturmaz, bu nedenle çalışma zamanında test edin: - **Başarılı satın alma**: v3'te varsayılan `paywallViewDidFinishPurchase` görünümü kapatıyordu. v4'te `flowViewDidFinishPurchase` zorunludur ve varsayılan davranışı yoktur — bu davranışı istiyorsanız görünümü kendiniz kapatın. - **Android sistem geri tuşu**: Artık varsayılan olarak bir flow'u kapatmaz. Eylem, `AndroidSystemBackAction` olarak `flowViewDidPerformAction`'a iletilir — geri tuşunun flow'u kapatmasını istiyorsanız bunu orada ele alın. - **URL açma**: Varsayılan `flowViewDidPerformAction` artık `OpenUrlAction`'ı URL'yi yerel olarak açarak işler (kontrol panelindeki uygulama içi veya harici tarayıcı ayarına uyar); `CloseAction`'da ise görünümü kapatmaya devam eder. URL'leri kendiniz işlemek istiyorsanız callback'i geçersiz kılın. - **Görünüm hataları**: `flowViewDidReceiveError` zorunludur ve kapatma işlemi sizin implementasyonunuza bağlıdır. v3 entegrasyonunuz render hatalarında görünümün otomatik olarak kapanmasına dayanıyorsa, bu callback içinde `view.dismiss()` çağırın. - **Görünüm yaşam döngüsü**: Bir flow veya onboarding görünümünü kapatmak, onu bellekten serbest bırakır. Kapatılmış bir görünüm artık yeniden gösterilemez — bunun yerine yeni bir tane oluşturun. ## Onboarding API'sinin kullanımdan kaldırılması \{#onboarding-api-deprecation\} Eski onboarding API'si, v4.0'da [Flow Builder](adapty-flow-builder) lehine kullanımdan kaldırılmıştır. Çalışmaya devam etmektedir; IDE'niz `@Deprecated` anotasyonları aracılığıyla kullanımdan kaldırılan sembolleri işaretler — çalışma zamanında herhangi bir uyarı gösterilmez. Bu semboller gelecekteki bir sürümde kaldırılacağından, onboarding'lerinizi Flow Builder'a taşımayı planlamanız önerilir. Kullanımdan kaldırılan semboller: `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView`, `presentOnboardingView`, `dismissOnboardingView`, `setOnboardingsEventsObserver`, `AdaptyOnboarding`, `AdaptyUIOnboardingView`, `AdaptyUIOnboardingPlatformView`, `AdaptyUIOnboardingsEventsObserver` ve onboarding durum, girdi ile analitik modelleri. --- # File: flutter-migration-guide-310 --- --- title: "Flutter Adapty SDK 3.10.0 için Geçiş Rehberi" description: "" --- Adapty SDK 3.10.0, bazı geliştirmeler içeren büyük bir sürümdür. Bu değişiklikler için aşağıdaki geçiş adımlarını uygulamanız gerekebilir: 1. `makePurchase` metodunu, tek tek parametreler yerine `AdaptyPurchaseParameters` kullanacak şekilde güncelleyin. 2. `AdaptyPaywall` modelinde `vendorProductIds` yerine `productIdentifiers` kullanın. ## makePurchase metodunu güncelleyin \{#update-makepurchase-method\} `makePurchase` metodu artık ayrı ayrı `subscriptionUpdateParams` ve `isOfferPersonalized` argümanları yerine `AdaptyPurchaseParameters` kullanıyor. Bu değişiklik daha iyi tip güvenliği sağlar ve satın alma parametrelerinin gelecekte genişletilmesine olanak tanır. ```diff showLineNumbers - final purchaseResult = await adapty.makePurchase( - product: product, - subscriptionUpdateParams: subscriptionUpdateParams, - isOfferPersonalized: true, - ); + final parameters = AdaptyPurchaseParametersBuilder() + ..setSubscriptionUpdateParams(subscriptionUpdateParams) + ..setIsOfferPersonalized(true) + ..setObfuscatedAccountId('your-account-id') + ..setObfuscatedProfileId('your-profile-id'); + final purchaseResult = await adapty.makePurchase( + product: product, + parameters: parameters.build(), + ); ``` Ek parametreye ihtiyaç duymuyorsanız şu şekilde kullanabilirsiniz: ```dart showLineNumbers final purchaseResult = await adapty.makePurchase( product: product, ); ``` ## AdaptyPaywall model kullanımını güncelleyin \{#update-adaptyapaywall-model-usage\} `vendorProductIds` özelliği kullanımdan kaldırılmış olup yerini `productIdentifiers` almıştır. Yeni özellik, düz string'ler yerine `AdaptyProductIdentifier` nesneleri döndürerek daha yapılandırılmış ürün bilgisi sunar. ```diff showLineNumbers - paywall.vendorProductIds.map((vendorId) => - ListTextTile(title: vendorId) - ).toList() + paywall.productIdentifiers.map((productId) => + ListTextTile(title: productId.vendorProductId) + ).toList() ``` `AdaptyProductIdentifier` nesnesi, `vendorProductId` özelliği aracılığıyla vendor ürün kimliğine erişim sağlar; mevcut işlevselliği korurken gelecekteki geliştirmeler için daha iyi bir yapı sunar. ## Geriye dönük uyumluluk \{#backward-compatibility\} Her iki değişiklik de geriye dönük uyumluluğu korumaktadır: - `makePurchase` içindeki eski parametreler kullanımdan kaldırılmış olsa da çalışmaya devam eder - `vendorProductIds` özelliği kullanımdan kaldırılmış olsa da erişilebilir olmaya devam eder - Mevcut kodunuz çalışmaya devam eder; ancak deprecation uyarıları göreceksiniz Gelecekteki uyumluluğu sağlamak ve geliştirilmiş tip güvenliği ile genişletilebilirlikten yararlanmak için kodunuzu yeni API'leri kullanacak şekilde güncellemenizi öneririz. --- # File: flutter-migration-guide-38 --- --- title: "Adapty Flutter SDK'yı v. 3.8'e Geçirme" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Flutter SDK v3.8'e geçin." --- Adapty SDK 3.8.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. Observer sınıfı ve metod adlarını güncelleyin. 2. Yedek paywall metod adını güncelleyin. 3. Olay işleme metodlarındaki view sınıf adını güncelleyin. ## Observer sınıfı ve metod adlarını güncelleme \{#update-observer-class-and-method-names\} Observer sınıfı ve kayıt metodu yeniden adlandırıldı: ```diff showLineNumbers - class MyObserver extends AdaptyUIObserver { + class MyObserver extends AdaptyUIPaywallsEventsObserver { @override void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { // Handle action } } // Register observer - AdaptyUI().setObserver(this); + AdaptyUI().setPaywallsEventsObserver(this); ``` ## Yedek paywall metod adını güncelleme \{#update-fallback-paywalls-method-name\} Yedek paywall ayarlama metodu basitleştirildi: ```diff showLineNumbers try { - await Adapty.setFallbackPaywalls(assetId); + await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Olay işleme yöntemlerinde view sınıfı adını güncelleme \{#update-view-class-name-in-event-handling-methods\} Tüm olay işleme yöntemleri artık `AdaptyUIView` yerine yeni `AdaptyUIPaywallView` sınıfını kullanıyor: ```diff showLineNumbers - void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) + void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) - void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile) + void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile) - void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error) + void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) - void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile) + void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) - void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) - void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) + void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) - void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) ``` --- # File: migration-to-flutter-sdk-34 --- --- title: "Adapty Flutter SDK'yı v3.4'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Flutter SDK v3.4'e geçiş yapın." --- Adapty SDK 3.4.0, sizin tarafınızda geçiş adımları gerektiren iyileştirmeler sunan önemli bir sürümdür. ## Yedek paywall dosyalarını güncelleme \{#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 paywall'ları yeni dosyalarla değiştirin](flutter-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleme \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Daha önce, işlemleri Adapty'ye bildirmek için farklı yöntemler kullanılıyordu. Yeni sürümde, `reportTransaction` yöntemi hem Android hem de iOS'ta tutarlı biçimde kullanılmalıdır. Bu yöntem, her işlemi Adapty'ye açıkça bildirir ve tanınmasını sağlar. Bir paywall kullanıldıysa, işlemi ilgili paywall'a bağlamak için varyasyon ID'sini geçirin. :::warning **İşlem bildirmeyi atlamayın!** `reportTransaction` çağrısını yapmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - // every time when calling transaction.finish() - if (Platform.isAndroid) { - try { - await Adapty().restorePurchases(); - } on AdaptyError catch (adaptyError) { - // handle the error - } catch (e) { - } - } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter330 --- --- title: "Adapty Flutter SDK'yı v3.3'e Geçirme" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Flutter SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.0, bazı iyileştirmeler içeren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Yedek paywall sağlama yöntemini güncelleyin. 2. `getProductsIntroductoryOfferEligibility` metodunu kaldırın. 3. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. 4. Observer mode uygulamasını güncelleyin. ## Yedek paywall sağlama yöntemini güncelleyin \{#update-method-for-providing-fallback-paywalls\} Daha önce bu yöntem, yedek paywall'u JSON dizesi (`jsonString`) olarak alıyordu; artık bunun yerine yerel yedek dosyanın yolunu (`assetId`) alıyor. ```diff showLineNumbers import 'dart:async' show Future; import 'dart:io' show Platform; -import 'package:flutter/services.dart' show rootBundle; -final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; -final jsonString = await rootBundle.loadString(filePath); +final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { - await adapty.setFallbackPaywalls(jsonString); + await adapty.setFallbackPaywalls(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Tam kod örneği için [Yedek paywall kullanımı](flutter-use-fallback-paywalls) sayfasına bakın. ## `getProductsIntroductoryOfferEligibility` metodunu kaldırın \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 öncesinde, ürün nesnesi kullanıcının uygun olup olmadığından bağımsız olarak her zaman teklifleri içeriyordu. Teklifi kullanmadan önce uygunluğu manuel olarak kontrol etmeniz gerekiyordu. Artık ürün nesnesi yalnızca kullanıcı uygunsa bir teklif içeriyor. Bu da uygunluğu ayrıca kontrol etmenize gerek kalmadığı anlamına gelir; bir teklif varsa kullanıcı zaten uygundur. ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleyin \{#update-third-party-integration-sdk-configuration\} Adapty Flutter SDK 3.3.0 ve sonrasında entegrasyonların düzgün çalışması için aşağıdaki bölümlerde açıklandığı gibi SDK yapılandırmalarınızı güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği şekilde 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 import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_config.dart'; try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } + await Adapty().setIntegrationIdentifier( + key: "adjust_device_id", + value: adid, + ); final attributionData = await Adjust.getAttribution(); var attribution = Map(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; - Adapty().updateAttribution( - attribution, - source: AdaptyAttributionSource.adjust, - networkUserId: adid, - ); + await Adapty().updateAttribution(attribution, source: "adjust"); } catch (e) { // handle the error } on AdaptyError catch (adaptyError) { // handle the error } ``` ### AirBridge Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge) sayfasına bakın. ```diff showLineNumbers import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart'; final deviceUUID = await Airbridge.state.deviceUUID; try { - final builder = AdaptyProfileParametersBuilder() - ..setAirbridgeDeviceId(deviceUUID); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "airbridge_device_id", + value: deviceUUID, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) sayfasına bakın. ```diff showLineNumbers import 'package:amplitude_flutter/amplitude.dart'; final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); final deviceId = await amplitude.getDeviceId(); final userId = await amplitude.getUserId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setAmplitudeDeviceId(deviceId) - ..setAmplitudeUserId(userId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "amplitude_user_id", + value: userId, + ); + await Adapty().setIntegrationIdentifier( + key: "amplitude_device_id", + value: deviceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // 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 import 'package:appmetrica_plugin/appmetrica_plugin.dart'; final deviceId = await AppMetrica.deviceId; if (deviceId != null) { try { - final builder = AdaptyProfileParametersBuilder() - ..setAppmetricaDeviceId(deviceId) - ..setAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceId, + ); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID", + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` ### 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 import 'package:appsflyer_sdk/appsflyer_sdk.dart'; AppsflyerSdk appsflyerSdk = AppsflyerSdk(); appsflyerSdk.onInstallConversionData((data) async { try { final appsFlyerUID = await appsFlyerSdk.getAppsFlyerUID(); - await Adapty().updateAttribution( - data, - source: AdaptyAttributionSource.appsflyer, - networkUserId: appsFlyerUID, - ); + await Adapty().setIntegrationIdentifier( + key: "appsflyer_id", + value: appsFlyerUID, + ); + + await Adapty().updateAttribution(data, source: "appsflyer"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } }); appsflyerSdk.initSdk( registerConversionDataCallback: true, registerOnAppOpenAttributionCallback: true, registerOnDeepLinkingCallback: true, ); ``` ### 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) sayfasına bakın. ```diff showLineNumbers FlutterBranchSdk.initSession().listen((data) async { try { + await Adapty().setIntegrationIdentifier( + key: "branch_id", + value: , + ); - await Adapty().updateAttribution(data, source: AdaptyAttributionSource.branch); + await Adapty().updateAttribution(data, source: "branch"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ); ``` ### Firebase ve Google Analytics Mobil uygulama kodunuzu aşağıda gösterildiği şekilde 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 final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; try { - final builder = AdaptyProfileParametersBuilder() - ..setFirebaseAppInstanceId(appInstanceId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Mixpanel entegrasyonu için SDK yapılandırması](mixpanel#sdk-configuration) sayfasına bakın. ```diff showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setMixpanelUserId(distinctId); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "mixpanel_user_id", + value: distinctId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) sayfasına bakın. ```diff showLineNumbers OneSignal.shared.setSubscriptionObserver((changes) { final playerId = changes.to.userId; if (playerId != null) { - final builder = - AdaptyProfileParametersBuilder() - ..setOneSignalPlayerId(playerId); - // ..setOneSignalSubscriptionId(playerId); try { - Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId, + ); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle error } } }); ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırması](pushwoosh#sdk-configuration) sayfasına bakın. ```diff showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; - final builder = AdaptyProfileParametersBuilder() - ..setPushwooshHWID(hwid); try { - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: hwid, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Observer mode uygulamasını güncelleyin \{#update-observer-mode-implementation\} Paywall'ları işlemlerle nasıl ilişkilendirdiğinizi güncelleyin. Daha önce `variationId`'yi atamak için `setVariationId` metodunu kullanıyordunuz. Artık `variationId`'yi doğrudan yeni `reportTransaction` metoduyla işlemi kaydederken ekleyebilirsiniz. Nihai kod örneği için [Observer mode'da paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode-flutter) sayfasına bakın. :::warning İşlemi `reportTransaction` metoduyla kaydetmeyi unutmayın. Bu adımı atladığınızda Adapty işlemi tanımayacak, access level vermeyecek, analize dahil etmeyecek ve entegrasyonlara göndermeyecektir. Bu adım zorunludur! ::: ```diff showLineNumbers try { - await Adapty().setVariationId("YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID"); + // every time when calling transaction.finish() + await Adapty().reportTransaction( + "YOUR_TRANSACTION_ID", + variationId: "PAYWALL_VARIATION_ID", // optional + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter-sdk-v3 --- --- title: "Adapty Flutter SDK'yı v3.0'a geçirme" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Flutter SDK v3.0'a geçin." --- Adapty SDK v3.0, no-code ve kullanıcı dostu bir paywall oluşturma aracının yeni sürümü olan [Adapty Paywall Builder](adapty-paywall-builder) desteğini sunuyor. Maksimum esnekliği ve zengin tasarım özellikleriyle paywalllarınız çok daha etkili ve kârlı hale gelecek. :::info AdaptyUI kütüphanesinin kullanımdan kaldırıldığını ve artık AdaptySDK'nın bir parçası olarak dahil edildiğini lütfen unutmayın. ::: ## AdaptyUI SDK'yı Kaldırma \{#remove-adaptyui-sdk\} 1. AdaptyUI artık Adapty SDK içinde bir modül haline geldiğinden, `pubspec.yaml` dosyanızdan `adapty_ui_flutter` bağımlılığını kaldırın: ```diff showLineNumbers dependencies: + adapty_flutter: ^3.2.1 - adapty_flutter: ^2.10.3 - adapty_ui_flutter: ^2.1.3 ``` 2. Şu komutu çalıştırın: ```bash showLineNumbers title="Bash" flutter pub get ``` ## Adapty SDK'yı Yapılandırma \{#configure-adapty-sdks\} Daha önce Adapty SDK yapılandırması için `Adapty-Info.plist` ve `AndroidManifest.xml` dosyalarını kullanmanız gerekiyordu. Artık ek dosyalara gerek yok. Bunun yerine, tüm gerekli parametreleri aktivasyon sırasında doğrudan sağlayabilirsiniz. Adapty SDK'yı yalnızca bir kez yapılandırmanız gerekir; bunu genellikle uygulamanızın yaşam döngüsünün başında yapın. ### Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} 1. AdaptyUI SDK import'unu uygulamanızdan aşağıdaki şekilde kaldırın: ```diff showLineNumbers import 'package:adapty_flutter/adapty_flutter.dart'; - import 'package:adapty_ui_flutter/adapty_ui_flutter.dart'; ``` 2. Adapty SDK aktivasyonunu şu şekilde güncelleyin: ```diff showLineNumbers try { - Adapty().activate(); + await Adapty().activate( + configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') + ..withLogLevel(AdaptyLogLevel.debug) + ..withObserverMode(false) + ..withCustomerUserId(null) + ..withIpAddressCollectionDisabled(false) + ..withIdfaCollectionDisabled(false), + ); } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ----------------------------------- | -------- | ------------------------------------------------------------ | | **PUBLIC_SDK_KEY** | zorunlu | Adapty'deki uygulama ayarlarınızın **Public SDK key** alanında bulabileceğiniz anahtar: [**App settings**-> **General** sekmesi -> **API keys** alt bölümü](https://app.adapty.io/settings/general) | | **withLogLevel** | isteğe bağlı | Adapty, uygulamanızın işleyişine dair bilgi sunmak için hataları ve diğer önemli verileri kaydeder. Kullanılabilir log seviyeleri şunlardır:
  • error: Yalnızca hatalar kaydedilir.
  • warn: Kritik hatalara yol açmayan ancak dikkat edilmesi gereken hatalar ve SDK mesajları kaydedilir.
  • info: Hatalar, uyarılar ve çeşitli modüllerin yaşam döngüsünü kaydeden önemli bilgi mesajları kaydedilir.
  • verbose: Hata ayıklama sırasında işe yarayabilecek fonksiyon çağrıları, API sorguları gibi ek bilgiler kaydedilir.
| | **withObserverMode** | isteğe bağlı |

[Observer mode](observer-vs-full-mode) özelliğini kontrol eden bir boolean değer. Satın alma ve abonelik durumunu kendiniz yönetip Adapty'yi yalnızca abonelik etkinliklerini ve analizleri göndermek için kullanıyorsanız etkinleştirin.

Varsayılan değer `false`'tur.

🚧 Observer mode etkinken Adapty SDK hiçbir işlemi kapatmaz, bu nedenle bunu kendiniz yönettiğinizden emin olun.

| | **withCustomerUserId** | isteğe bağlı | Sisteminizdeki kullanıcı tanımlayıcısı. Etkinlikleri doğru profile bağlamak için abonelik ve analitik etkinliklerinde gönderilir. Ayrıca [**Profiles and Segments**](https://app.adapty.io/profiles/users) menüsünden `customerUserId` ile müşteri arayabilirsiniz. | | **withIdfaCollectionDisabled** | isteğe bağlı |

IDFA toplama ve paylaşımını devre dışı bırakmak için `true` olarak ayarlayın.

Kullanıcı IP adresi paylaşımı.

Varsayılan değer `false`'tur.

IDFA toplama hakkında daha fazla bilgi için [Analytics integration](analytics-integration#disable-collection-of-advertising-identifiers) bölümüne bakın.

| | **withIpAddressCollectionDisabled** | isteğe bağlı |

Kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `true` olarak ayarlayın.

Varsayılan değer `false`'tur.

| ### Adapty SDK'nın AdaptyUI Modülünü Etkinleştirme \{#activate-adaptyui-module-of-adapty-sdk\} AdaptyUI modülünü yalnızca [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız yapılandırmanız gerekir: ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer: , ); } catch (e) { // handle the error } ``` AdaptyUI yapılandırmasının isteğe bağlı olduğunu unutmayın; AdaptyUI modülünü config olmadan da etkinleştirebilirsiniz. Ancak config kullanıyorsanız, içindeki tüm parametreler zorunludur. Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------------------ | :------- | :----------------------------------------------------------- | | **memoryStorageTotalCostLimit** | zorunlu | Depolamanın bayt cinsinden toplam maliyet sınırı. | | **memoryStorageCountLimit** | zorunlu | Bellek depolamasının öğe sayısı sınırı. | | **diskStorageSizeLimit** | zorunlu | Diskteki depolama için bayt cinsinden dosya boyutu sınırı. 0 değeri sınır olmadığı anlamına gelir. | --- # End of Documentation _Generated on: 2026-07-24T13:02:34.317Z_ _Successfully processed: 44/44 files_