Flow'ları ve paywall'ları görüntüleme - React Native
Flow Builder’da bir flow veya paywall oluşturduysanız, onu kullanıcıya göstermek için mobil uygulama kodunuzda render etme derdine girmenize gerek yoktur. Böyle bir flow, hem içinde ne gösterileceğini hem de nasıl gösterileceğini içerir.
Başlamadan önce şunlardan emin olun:
- Bir flow veya paywall oluşturdunuz.
- Onu bir placement’a eklediniz.
- Flow’u getirdiniz ve view’i hazırladınız.
Bu rehber yalnızca flow’lar ve Paywall Builder paywall’ları içindir; bunlar SDK v4.0 veya sonrasını gerektirir. Flow sunma süreci, remote config paywall’ları için farklıdır.
- Remote config paywall’larını sunmak için bkz. Remote config ile tasarlanan paywall’ı render etme.
Adapty React Native SDK, flow’ları ve paywall’ları sunmak için iki yol sağlar:
-
React bileşeni: Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır.
-
Modal sunum
React bileşeni
Bir flow’u mevcut bileşen ağacınıza gömmek için, AdaptyFlowView bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın. Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır.
AdaptyFlowView bileşeni, view’ini render edildiğinde oluşturur; yani yapılandırma ve görseller yüklendiğinde. Bunları önceden yüklemek için, uygulamanızda daha erken bir noktada aynı flow için createFlowView çağırın. Bileşen daha sonra önbelleğe alınmış verileri yeniden kullanır ve indirmeleri beklemeden render eder.
function MyFlow({ flow }) {
const flowParams = useMemo(() => ({
loadTimeoutMs: 3000,
}), []);
const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>(() => {}, []);
const onProductSelected = useCallback<FlowEventHandlers['onProductSelected']>((productId) => {}, []);
const onPurchaseStarted = useCallback<FlowEventHandlers['onPurchaseStarted']>((product) => {}, []);
const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []);
const onPurchaseFailed = useCallback<FlowEventHandlers['onPurchaseFailed']>((error, product) => {}, []);
const onRestoreStarted = useCallback<FlowEventHandlers['onRestoreStarted']>(() => {}, []);
const onRestoreCompleted = useCallback<FlowEventHandlers['onRestoreCompleted']>((profile) => {}, []);
const onRestoreFailed = useCallback<FlowEventHandlers['onRestoreFailed']>((error) => {}, []);
const onAppeared = useCallback<FlowEventHandlers['onAppeared']>(() => {}, []);
const onError = useCallback<FlowEventHandlers['onError']>((error) => {}, []);
const onLoadingProductsFailed = useCallback<FlowEventHandlers['onLoadingProductsFailed']>((error) => {}, []);
const onUrlPress = useCallback<FlowEventHandlers['onUrlPress']>((url) => {}, []);
const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>((actionId) => {}, []);
const onWebPaymentNavigationFinished = useCallback<FlowEventHandlers['onWebPaymentNavigationFinished']>(() => {}, []);
return (
<AdaptyFlowView
flow={flow}
params={flowParams}
style={styles.flow}
onCloseButtonPress={onCloseButtonPress}
onProductSelected={onProductSelected}
onPurchaseStarted={onPurchaseStarted}
onPurchaseCompleted={onPurchaseCompleted}
onPurchaseFailed={onPurchaseFailed}
onRestoreStarted={onRestoreStarted}
onRestoreCompleted={onRestoreCompleted}
onRestoreFailed={onRestoreFailed}
onAppeared={onAppeared}
onError={onError}
onLoadingProductsFailed={onLoadingProductsFailed}
onCustomAction={onCustomAction}
onUrlPress={onUrlPress}
onWebPaymentNavigationFinished={onWebPaymentNavigationFinished}
/>
);
}Modal sunum
Bir flow’u bağımsız bir ekran olarak görüntülemek için, createFlowView metoduyla oluşturulan view üzerinde view.present() metodunu kullanın. Her view yalnızca bir kez kullanılabilir. Flow’u tekrar görüntülemeniz gerekirse, yeni bir view örneği oluşturmak için createFlowView’u bir kez daha çağırın.
Aynı view’i yeniden oluşturmadan tekrar kullanmak yasaktır. Bu, bir AdaptyUIError.viewAlreadyPresented hatasıyla sonuçlanır.
const view = await createFlowView(flow);
// Optional: handle flow events (close, purchase, restore, etc)
// view.setEventHandlers({ ... });
try {
await view.present();
} catch (error) {
// handle the error
}setEventHandlers’ı birden çok kez çağırmak, sağladığınız işleyicileri geçersiz kılar; söz konusu belirli olaylar için hem varsayılan hem de önceden ayarlanmış işleyicilerin yerini alır.
iOS sunum stilini yapılandırın
Flow’un iOS’ta nasıl sunulacağını, present() metoduna iosPresentationStyle parametresini ileterek yapılandırın. Parametre 'full_screen' (varsayılan) veya 'page_sheet' değerlerini kabul eder.
try {
await view.present({ iosPresentationStyle: 'page_sheet' });
} catch (error) {
// handle the error
}Geliştirici tanımlı zamanlayıcı kullanımı
Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için, bu örnekte CUSTOM_TIMER_NY olan timerId’yi kullanın; bu, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının Timer ID’sidir. Bu sayede uygulamanız zamanlayıcıyı doğru değerle dinamik olarak günceller; örneğin 13g 09s 03d 34s (zamanlayıcının bitiş zamanı olan Yılbaşı’ndan mevcut zamanın çıkarılmasıyla hesaplanır).
Bu örnekte CUSTOM_TIMER_NY, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının Timer ID’sidir. timerResolver, uygulamanızın zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar; örneğin 13g 09s 03d 34s (zamanlayıcının bitiş zamanı olan Yılbaşı’ndan mevcut zamanın çıkarılmasıyla hesaplanır).
Diyalog gösterme
Android’de bir flow view sunulduğunda, yerel uyarı diyalogları yerine bu metodu kullanın. Android’de normal RN uyarıları flow view’in arkasında görünür, bu da onları kullanıcılara görünmez kılar. Bu metot, tüm platformlarda diyalogun flow’un üzerinde düzgün şekilde sunulmasını sağlar.
try {
const action = await view.showDialog({
title: 'Close paywall?',
content: 'You will lose access to exclusive offers.',
primaryActionTitle: 'Stay',
secondaryActionTitle: 'Close',
});
if (action === 'secondary') {
// User confirmed - close the flow
await view.dismiss();
}
// If primary - do nothing, user stays
} catch (error) {
// handle error
}Bir aboneliği başka biriyle değiştirme
Android’de başka bir abonelik etkinken bir kullanıcı yeni bir abonelik satın almaya çalıştığında, flow view’i oluştururken abonelik güncelleme parametrelerini geçirerek yeni satın almanın nasıl yönetileceğini kontrol edebilirsiniz. Mevcut aboneliği yenisiyle değiştirmek için, createFlowView içinde oldSubVendorProductId ve prorationMode parametreleriyle birlikte productPurchaseParams kullanın.
const productPurchaseParams = flow.paywalls
.flatMap((variation) => variation.productIdentifiers)
.map((productId) => {
let params = {};
if (Platform.OS === 'android') {
params.android = {
subscriptionUpdateParams: {
oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
prorationMode: 'with_time_proration',
},
};
}
return { productId, params };
});
const view = await createFlowView(flow, { productPurchaseParams });Paywall Builder kullanarak bir paywall özelleştirdiyseniz, onu kullanıcıya göstermek için mobil uygulama kodunuzda render etme derdine girmenize gerek yoktur. Böyle bir paywall, hem paywall içinde ne gösterileceğini hem de nasıl gösterileceğini içerir.
Başlamadan önce şunlardan emin olun:
- Bir paywall oluşturdunuz.
- Paywall’ı bir placement’a eklediniz.
- Paywall’ı getirdiniz ve view’i hazırladınız.
Bu rehber yalnızca yeni Paywall Builder paywall’ları içindir; bunlar SDK v3.0 veya sonrasını gerektirir. Paywall sunma süreci, Paywall Builder’ın farklı sürümleriyle tasarlanan paywall’lar ve remote config paywall’ları için farklıdır.
- Remote config paywall’larını sunmak için bkz. Remote config ile tasarlanan paywall’ı render etme.
Adapty React Native SDK, paywall’ları sunmak için iki yol sağlar:
-
React bileşeni: Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır.
-
Modal sunum
React bileşeni
React bileşeni yaklaşımı SDK 3.14.0 veya üstünü gerektirir.
Bir paywallı mevcut bileşen ağacınıza gömmek için AdaptyPaywallView bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın. Gömülü bileşen, uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır.
Android’de, paywall durum çubuğunun arkasına uzanmıyorsa üst kısmında görsel bir katman belirebiilir. Paywalllarınız için bunu kapatmanızı öneririz. Bkz. Paywallın üst kısmındaki görsel katman (Android).
function MyPaywall({ paywall }) {
const paywallParams = useMemo(() => ({
loadTimeoutMs: 3000,
}), []);
const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []);
const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []);
const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []);
const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []);
const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []);
const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []);
const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []);
const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []);
const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []);
const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []);
const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []);
const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => {}, []);
const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []);
const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []);
return (
<AdaptyPaywallView
paywall={paywall}
params={paywallParams}
style={styles.paywall}
onCloseButtonPress={onCloseButtonPress}
onProductSelected={onProductSelected}
onPurchaseStarted={onPurchaseStarted}
onPurchaseCompleted={onPurchaseCompleted}
onPurchaseFailed={onPurchaseFailed}
onRestoreStarted={onRestoreStarted}
onRestoreCompleted={onRestoreCompleted}
onRestoreFailed={onRestoreFailed}
onPaywallShown={onPaywallShown}
onRenderingFailed={onRenderingFailed}
onLoadingProductsFailed={onLoadingProductsFailed}
onCustomAction={onCustomAction}
onUrlPress={onUrlPress}
onWebPaymentNavigationFinished={onWebPaymentNavigationFinished}
/>
);
}Modal sunum
Bir paywallı bağımsız bir ekran olarak göstermek için, createPaywallView 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’i bir kez daha çağırın.
Aynı view’ı yeniden oluşturmadan tekrar kullanmak yasaktır. Bu durum AdaptyUIError.viewAlreadyPresented hatasına yol açar.
const view = await createPaywallView(paywall);
// Optional: handle paywall events (close, purchase, restore, etc)
// view.setEventHandlers({ ... });
try {
await view.present();
} catch (error) {
// handle the error
}setEventHandlers’ı birden çok kez çağırmak, sağladığınız işleyicileri geçersiz kılar; söz konusu belirli olaylar için hem varsayılan hem de önceden ayarlanmış işleyicilerin yerini alır.
iOS sunum stilini yapılandırın
Paywall’ın iOS’ta nasıl sunulacağını, present() metoduna iosPresentationStyle parametresini ileterek yapılandırın. Parametre 'full_screen' (varsayılan) veya 'page_sheet' değerlerini kabul eder.
try {
await view.present({ iosPresentationStyle: 'page_sheet' });
} catch (error) {
// handle the error
}Geliştirici tanımlı zamanlayıcı kullanma
Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için, timerId’yi kullanın; bu örnekte, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının Timer ID’si olan CUSTOM_TIMER_NY. Bu, uygulamanızın zamanlayıcıyı 13d 09h 03m 34s gibi doğru değerle dinamik olarak güncellemesini sağlar (zamanlayıcının bitiş zamanı, örneğin Yılbaşı Günü, eksi mevcut zaman olarak hesaplanır).
Bu örnekte, CUSTOM_TIMER_NY, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının Timer ID’sidir. timerResolver, uygulamanızın zamanlayıcıyı 13d 09h 03m 34s gibi doğru değerle dinamik olarak güncellemesini sağlar (zamanlayıcının bitiş zamanı, örneğin Yılbaşı Günü, eksi mevcut zaman olarak hesaplanır).
Dialog gösterme
Android’de bir paywall view sunulduğunda, yerel uyarı dialogları yerine bu metodu kullanın. Android’de normal RN uyarıları paywall view’ın arkasında kalır ve kullanıcılar tarafından görülemez. Bu metot, tüm platformlarda paywallın üzerinde dialog’un düzgün şekilde sunulmasını sağlar.
try {
const action = await view.showDialog({
title: 'Close paywall?',
content: 'You will lose access to exclusive offers.',
primaryActionTitle: 'Stay',
secondaryActionTitle: 'Close',
});
if (action === 'secondary') {
// User confirmed - close the paywall
await view.dismiss();
}
// If primary - do nothing, user stays
} catch (error) {
// handle error
}Bir aboneliği diğeriyle değiştirme
Bir kullanıcı Android’de başka bir abonelik aktifken yeni bir abonelik satın almaya çalıştığında, paywall view’ı oluştururken abonelik güncelleme parametrelerini ileterek yeni satın almanın nasıl işleneceğini kontrol edebilirsiniz. Mevcut aboneliği yenisiyle değiştirmek için createPaywallView’de oldSubVendorProductId ve prorationMode parametreleriyle birlikte productPurchaseParams kullanın.
const productPurchaseParams = paywall.productIdentifiers.map((productId) => {
let params = {};
if (Platform.OS === 'android') {
params.android = {
subscriptionUpdateParams: {
oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
prorationMode: 'with_time_proration',
},
};
}
return { productId, params };
});
const view = await createPaywallView(paywall, { productPurchaseParams });Sorun giderme
Paywallın üst kısmındaki görsel katman (Android)
Bu ayar React Native SDK 3.15.5’ten itibaren desteklenmektedir ve yalnızca bare React Native projelerinde kullanılabilir.
Expo yönetilen iş akışı kullanıyorsanız bu Android kaynağını doğrudan ekleyemezsiniz. Bu ayarı uygulamak için, ilgili Android kaynağını ekleyen özel bir Expo config plugin oluşturmanız ve bunu app.config.js’e kaydetmeniz gerekir. Bunun nedeni Expo’nun yerel Android projesini sizin adınıza yönetmesidir.
AdaptyPaywallView durum çubuğunun arkasına uzanmıyorsa, üst kısmında yine de görsel bir kaplama görünebilir. Onu kaldırmak için uygulamanıza aşağıdaki boolean kaynağını ekleyin:
-
android/app/src/main/res/valueskonumuna gidin.bools.xmldosyası yoksa oluşturun. -
Aşağıdaki kaynağı ekleyin:
<resources>
<bool name="adapty_paywall_enable_safe_area_paddings">false</bool>
</resources>Değişikliklerin uygulamanızdaki tüm paywall’lar için genel olarak geçerli olduğunu unutmayın.