Реалізація Privacy Policy та Terms of Service екранів у мобільному додатку
Екрани Privacy Policy та Terms of Service — це не просто «відкрити WebView з URL». App Store та Google Play мають конкретні вимоги та додатки регулярно отримують відмови в ревю з-за неправильної інтеграції.
Вимоги App Store та Google Play
Apple вимагає посилання на Privacy Policy в App Store Connect — без неї додаток з IAP або запитом чутливих даних не пройде ревю (Guideline 5.1.1). Всередину додатку — при запиті персональних даних має бути доступне посилання на PP.
Google Play вимагає Privacy Policy URL у консолі розробника + наявність посилання всередину додатку, якщо він запитує розрішення, використовує дані дітей або фінансові дані.
Екран при першому запуску
Перший запуск — критична точка. Не можна показувати согласие як чекбокс «прийняти все» без можливості ознайомитися з текстом. Не можна робити кнопку «Прийняти» єдиною активною, поки користувач не проскролив документ — це тьмяний паттерн, який регулятори все частіше переслідують.
// Мінімально коректна реалізація
class ConsentScreen : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.btnAccept.isEnabled = false // недоступна до прочитання
binding.scrollView.setOnScrollChangeListener { _, _, scrollY, _, _ ->
val contentHeight = binding.scrollContent.height
val scrollHeight = binding.scrollView.height
// Активуємо після досягнення кінця
if (scrollY >= contentHeight - scrollHeight - 50) {
binding.btnAccept.isEnabled = true
}
}
binding.linkPrivacyPolicy.setOnClickListener {
openDocument(DocumentType.PRIVACY_POLICY)
}
}
}
Зберігати факт прийняття з версією документа та timestamp:
data class AcceptanceRecord(
val documentType: String, // "privacy_policy", "terms"
val version: String, // "2.1.0"
val acceptedAt: Long, // unix timestamp
val userId: String?
)
При оновленні документу — повторне прийняття тільки якщо зміни суттєві. Фіксуємо document_version в таблиці користувача на сервері.
WebView vs нативний екран
Завантаження з URL через WebView — гнучко (оновлення без релізу), але створює залежність від сети. При відсутності інтернету користувач не може ознайомитися з документом та прийняти. Рішення: кешувати останню версію локально, показувати кешовану при відсутності сети.
class PolicyDocumentLoader {
func loadPolicy(_ type: PolicyType) async -> PolicyDocument {
// Пробуємо завантажити свіжу версію
if let fresh = try? await fetchFromServer(type) {
cache.save(fresh, for: type)
return fresh
}
// Fallback на кеш
if let cached = cache.load(for: type) {
return cached
}
// Останній резерв — bundled версія з додатку
return loadBundled(type)
}
}
Bundled версія — завжди актуальна на момент релізу — шʼється в додаток. Не може бути застарілою при встановленні.
Deep link до конкретного розділу
Для compliance іноді потрібно відкрити конкретний розділ: наприклад, з екрану запиту розрішень камери — одразу до розділу «Фото та відео» у Privacy Policy. WKWebView підтримує URL fragment (#camera-section), якщо документ це підтримує.
Терміни
Реалізація екранів з WebView, кешуванням, логуванням прийняття: 1 день. Стоимость рассчитывается індивідуально.







