主题
ConsentManager 继承自: ft.Service, BaseControl
使用 Google 的用户消息平台(UMP)收集并管理用户对广告的同意。
使用此服务来请求同意信息、展示同意表单(例如 GDPR/EEA 同意对话框)与隐私选项表单, 并在请求广告之前查询同意状态。
典型流程如下:
request_consent_info_update(每次启动应用时);load_and_show_consent_form_if_required(仅在需要时才展示表单);can_request_ads(用于决定是否开始加载广告)。
更多信息见 AdMob 文档。
抛出异常: FletUnsupportedPlatformException:在 Web 和/或非移动端平台上使用时抛出。
示例
python
import flet as ft
import flet_ads as fta
def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
# mobile-only
supported = not page.web and page.platform.is_mobile()
if supported:
page.services.append(consent_manager := fta.ConsentManager())
async def refresh_status():
consent_status = await consent_manager.get_consent_status()
privacy_status = await consent_manager.get_privacy_options_requirement_status()
can_request = await consent_manager.can_request_ads()
status.value = (
f"Consent status: {consent_status.name}\n"
f"Privacy options required: {privacy_status.name}\n"
f"Can request ads: {can_request}"
)
# Only surface the privacy options entry point when we are required to.
privacy_button.visible = (
privacy_status == fta.PrivacyOptionsRequirementStatus.REQUIRED
)
page.update()
async def gather_consent(e: ft.Event[ft.OutlinedButton]):
status.value = "Gathering consent…"
status.update()
try:
# Remember to remove the debug settings in production.
await consent_manager.request_consent_info_update(
fta.ConsentRequestParameters(
consent_debug_settings=fta.ConsentDebugSettings(
debug_geography=fta.DebugGeography.EEA,
# test_identifiers=["<HASHED_ID>"], # for physical devices only
),
)
)
# Loads and shows the consent form only if consent is required.
await consent_manager.load_and_show_consent_form_if_required()
await refresh_status()
# At this point, if `can_request_ads()` is True, it is safe to start
# loading ads (e.g. fta.BannerAd / fta.InterstitialAd).
except Exception as ex:
status.value = f"Error: {ex}"
status.update()
async def show_privacy_options(e: ft.Event[ft.OutlinedButton]):
try:
await consent_manager.show_privacy_options_form()
await refresh_status()
except Exception as ex:
status.value = f"Error: {ex}"
page.update()
async def reset_consent(e: ft.Event[ft.OutlinedButton]):
# For testing only: resets consent so you can replay the flow.
try:
await consent_manager.reset()
status.value = 'Consent reset. Tap "Gather consent" to begin again.'
privacy_button.visible = False
except Exception as ex:
status.value = f"Error: {ex}"
page.update()
page.add(
ft.SafeArea(
content=ft.Column(
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text(
"Gather user consent (e.g. GDPR/EEA) with Google's User "
"Messaging Platform before requesting ads.",
text_align=ft.TextAlign.CENTER,
),
ft.OutlinedButton(
content="Gather consent",
on_click=gather_consent,
disabled=not supported,
),
privacy_button := ft.OutlinedButton(
content="Show privacy options form",
visible=False,
on_click=show_privacy_options,
),
ft.OutlinedButton(
content="Reset consent (testing)",
on_click=reset_consent,
disabled=not supported,
),
ft.Divider(),
status := ft.Text('Tap "Gather consent" to begin.'),
],
)
),
)
if __name__ == "__main__":
ft.run(main)属性
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
data | Any | skip_ | 任意类型的自定义数据。 |
key | Optional['KeyValue'] | None | 用于在更新之间保持控件身份稳定的 key。 |
只读属性
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
parent | Optional['BaseControl'] | — | The direct ancestor(parent) of this control. It defaults to None and will only have a value when this control is mounted (added to the page tree). Page 控件(树的根)为例外 —— 它始终 parent=None。 |
page | 'Page' | — | 此控件所属的页面。 |
方法
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
before_update | — | — | — |
request_consent_info_update | — | — | Requests an update of the user's consent information. This should be called (and awaited) at every app launch, before loading/showing a consent form or reading the consent status. Args: params: Parameters such as debug settings (useful for testing the form during development) or the under-age tag. If None, default parameters are used. |
is_consent_form_available | bool | — | Checks whether a consent form is available to be loaded and shown. Note: request_consent_info_update should be awaited before calling this method. Returns: True if a consent form is available, False otherwise. |
get_consent_status | ConsentStatus | — | Get the user’s consent status. This value is cached between app sessions and can be read before requesting an update of the consent information. Returns: The user's current consent status. |
can_request_ads | bool | — | Indicates whether the app has gathered enough consent to request ads. Returns: True if ads can be requested, False otherwise. |
get_privacy_options_requirement_status | PrivacyOptionsRequirementStatus | — | Gets the requirement status for showing a privacy options entry point. Returns: Whether a privacy options entry point (for example, a button that calls show_privacy_options_form) is required. |
load_and_show_consent_form_if_required | — | — | Loads a consent form and immediately shows it if consent is required. If consent is not required, this method completes without showing anything. This is the simplest way to gather consent: call request_consent_info_update first, then this method. |
show_privacy_options_form | — | — | Presents the privacy options form to the user. This lets users change or withdraw their consent after the initial choice. Only present it when get_privacy_options_requirement_status returns REQUIRED. |
reset | — | — | Resets the consent state. Warning: This is intended only for testing, allowing you to simulate a first-time user. It should not be used in production. |
init | — | — | — |
is_isolated | — | — | Return whether this control is marked as isolated. 被隔离的控件不会参与父级驱动的更新遍历,需要自行管理更新边界。 |
build | — | — | 在控件初始化期间调用一次,用于定义其子控件。 page 属性在此方法中可用。 |
before_event | — | — | 在事件处理器执行前拦截事件。 返回 False 取消分发,返回 True 或 None 则继续正常的事件处理。 |
did_mount | — | — | 在控件挂载到页面树之后调用。 可重写以启动需要已挂载页面的资源,例如订阅、定时器或服务监听。 |
will_unmount | — | — | 在控件从页面树移除之前调用。 可重写以释放 did_mount() 中创建的资源,例如订阅、定时器或外部句柄。 |
get_data_channel | — | — | Resolve the [DataChannel] allocated on the Dart side for this widget. Pattern: on_data_channel_open: Optional[ft.EventHandler[DataChannelOpenEvent]] = None def init(self): self.on_data_channel_open = self._on_open def _on_open(self, e): self._channel = self.get_data_channel(e.channel_id) Idempotent — the underlying Connection caches DataChannels by id, so repeated calls return the same instance. No error path: the id always comes from a framework-fired event, so by the time this runs the channel exists on both sides. |
update | None | — | 请求更新该控件的 UI。 在修改控件状态或属性后调用。 控件必须已挂载到页面,并且未被冻结。 |