|
| 1 | +from typing import Optional |
| 2 | + |
| 3 | +import flet as ft |
| 4 | +from flet_ads.types import ( |
| 5 | + ConsentRequestParameters, |
| 6 | + ConsentStatus, |
| 7 | + PrivacyOptionsRequirementStatus, |
| 8 | +) |
| 9 | + |
| 10 | +__all__ = ["ConsentManager"] |
| 11 | + |
| 12 | + |
| 13 | +@ft.control("ConsentManager") |
| 14 | +class ConsentManager(ft.Service): |
| 15 | + """ |
| 16 | + Gathers and manages user consent for ads using |
| 17 | + Google's User Messaging Platform (UMP). |
| 18 | +
|
| 19 | + Use this service to request consent information, present the consent form |
| 20 | + (for example, the GDPR/EEA consent dialog) and the privacy options form, |
| 21 | + and query the consent status before requesting ads. |
| 22 | +
|
| 23 | + A typical flow looks like this: |
| 24 | +
|
| 25 | + 1. :meth:`request_consent_info_update` (at every app launch); |
| 26 | + 2. :meth:`load_and_show_consent_form_if_required` (shows the form only if needed); |
| 27 | + 3. :meth:`can_request_ads` (to decide whether to start loading ads). |
| 28 | +
|
| 29 | + More info in the [AdMob documentation](https://developers.google.com/admob/flutter/privacy). |
| 30 | +
|
| 31 | + Raises: |
| 32 | + FletUnsupportedPlatformException: When any of its methods are called on |
| 33 | + a web and/or non-mobile platform. |
| 34 | + """ # noqa: E501 |
| 35 | + |
| 36 | + def init(self): |
| 37 | + super().init() |
| 38 | + if self.page.web or not self.page.platform.is_mobile(): |
| 39 | + raise ft.FletUnsupportedPlatformException( |
| 40 | + f"{self.__class__.__name__} is only supported on " |
| 41 | + f"Mobile (Android and iOS)" |
| 42 | + ) |
| 43 | + |
| 44 | + async def request_consent_info_update( |
| 45 | + self, params: Optional[ConsentRequestParameters] = None |
| 46 | + ): |
| 47 | + """ |
| 48 | + Requests an update of the user's consent information. |
| 49 | +
|
| 50 | + This should be called (and awaited) at every app launch, before |
| 51 | + loading/showing a consent form or reading the consent status. |
| 52 | +
|
| 53 | + Args: |
| 54 | + params: Parameters such as debug settings (useful for |
| 55 | + testing the form during development) or the under-age tag. |
| 56 | + If `None`, default parameters are used. |
| 57 | + """ |
| 58 | + await self._invoke_method("request_consent_info_update", {"params": params}) |
| 59 | + |
| 60 | + async def is_consent_form_available(self) -> bool: |
| 61 | + """ |
| 62 | + Checks whether a consent form is available to be loaded and shown. |
| 63 | +
|
| 64 | + Note: |
| 65 | + :meth:`request_consent_info_update` should be awaited before calling |
| 66 | + this method. |
| 67 | +
|
| 68 | + Returns: |
| 69 | + `True` if a consent form is available, `False` otherwise. |
| 70 | + """ |
| 71 | + return await self._invoke_method("is_consent_form_available") |
| 72 | + |
| 73 | + async def get_consent_status(self) -> ConsentStatus: |
| 74 | + """ |
| 75 | + Get the user’s consent status. |
| 76 | +
|
| 77 | + This value is cached between app sessions and can be read before |
| 78 | + requesting an update of the consent information. |
| 79 | +
|
| 80 | + Returns: |
| 81 | + The user's current consent status. |
| 82 | + """ |
| 83 | + return ConsentStatus(await self._invoke_method("get_consent_status")) |
| 84 | + |
| 85 | + async def can_request_ads(self) -> bool: |
| 86 | + """ |
| 87 | + Indicates whether the app has gathered enough consent to request ads. |
| 88 | +
|
| 89 | + Returns: |
| 90 | + `True` if ads can be requested, `False` otherwise. |
| 91 | + """ |
| 92 | + return bool(await self._invoke_method("can_request_ads")) |
| 93 | + |
| 94 | + async def get_privacy_options_requirement_status( |
| 95 | + self, |
| 96 | + ) -> PrivacyOptionsRequirementStatus: |
| 97 | + """ |
| 98 | + Gets the requirement status for showing a privacy options entry point. |
| 99 | +
|
| 100 | + Returns: |
| 101 | + Whether a privacy options entry point (for example, a button |
| 102 | + that calls :meth:`show_privacy_options_form`) is required. |
| 103 | + """ |
| 104 | + return PrivacyOptionsRequirementStatus( |
| 105 | + await self._invoke_method("get_privacy_options_requirement_status") |
| 106 | + ) |
| 107 | + |
| 108 | + async def load_and_show_consent_form_if_required(self): |
| 109 | + """ |
| 110 | + Loads a consent form and immediately shows it if consent is required. |
| 111 | +
|
| 112 | + If consent is not required, this method completes without showing |
| 113 | + anything. This is the simplest way to gather consent: call |
| 114 | + :meth:`request_consent_info_update` first, then this method. |
| 115 | + """ |
| 116 | + await self._invoke_method("load_and_show_consent_form_if_required") |
| 117 | + |
| 118 | + async def show_privacy_options_form(self): |
| 119 | + """ |
| 120 | + Presents the privacy options form to the user. |
| 121 | +
|
| 122 | + This lets users change or withdraw their consent after the initial |
| 123 | + choice. Only present it when :meth:`get_privacy_options_requirement_status` |
| 124 | + returns :attr:`flet_ads.PrivacyOptionsRequirementStatus.REQUIRED`. |
| 125 | + """ |
| 126 | + await self._invoke_method("show_privacy_options_form") |
| 127 | + |
| 128 | + async def reset(self): |
| 129 | + """ |
| 130 | + Resets the consent state. |
| 131 | +
|
| 132 | + Warning: |
| 133 | + This is intended only for testing, allowing you to simulate a first-time |
| 134 | + user. It should not be used in production. |
| 135 | + """ |
| 136 | + await self._invoke_method("reset") |
0 commit comments