flet-ads 0.85.3.dev0__tar.gz → 0.86.0.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {flet_ads-0.85.3.dev0/src/flet_ads.egg-info → flet_ads-0.86.0.dev0}/PKG-INFO +2 -2
  2. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/pyproject.toml +2 -2
  3. flet_ads-0.86.0.dev0/src/flet_ads/__init__.py +29 -0
  4. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads/base_ad.py +2 -1
  5. flet_ads-0.86.0.dev0/src/flet_ads/consent_manager.py +136 -0
  6. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads/native_ad.py +2 -2
  7. flet_ads-0.86.0.dev0/src/flet_ads/types.py +265 -0
  8. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0/src/flet_ads.egg-info}/PKG-INFO +2 -2
  9. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads.egg-info/SOURCES.txt +3 -0
  10. flet_ads-0.86.0.dev0/src/flet_ads.egg-info/requires.txt +1 -0
  11. flet_ads-0.86.0.dev0/src/flutter/flet_ads/lib/src/consent_manager.dart +92 -0
  12. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/src/extension.dart +3 -0
  13. flet_ads-0.86.0.dev0/src/flutter/flet_ads/lib/utils/consent.dart +25 -0
  14. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/pubspec.yaml +1 -1
  15. flet_ads-0.85.3.dev0/src/flet_ads/__init__.py +0 -17
  16. flet_ads-0.85.3.dev0/src/flet_ads/types.py +0 -131
  17. flet_ads-0.85.3.dev0/src/flet_ads.egg-info/requires.txt +0 -1
  18. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/LICENSE +0 -0
  19. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/README.md +0 -0
  20. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/setup.cfg +0 -0
  21. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads/banner_ad.py +0 -0
  22. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads/interstitial_ad.py +0 -0
  23. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads.egg-info/dependency_links.txt +0 -0
  24. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flet_ads.egg-info/top_level.txt +0 -0
  25. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/flet_ads.dart +0 -0
  26. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/src/banner.dart +0 -0
  27. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/src/interstitial.dart +0 -0
  28. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/src/native.dart +0 -0
  29. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/utils/ads.dart +0 -0
  30. {flet_ads-0.85.3.dev0 → flet_ads-0.86.0.dev0}/src/flutter/flet_ads/lib/utils/native.dart +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-ads
3
- Version: 0.85.3.dev0
3
+ Version: 0.86.0.dev0
4
4
  Summary: Display Google Ads in Flet apps.
5
5
  Author-email: Flet contributors <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -11,7 +11,7 @@ Project-URL: Issues, https://github.com/flet-dev/flet/issues
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: flet==0.85.3.dev0
14
+ Requires-Dist: flet==0.86.0.dev0
15
15
  Dynamic: license-file
16
16
 
17
17
  # flet-ads
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "flet-ads"
3
- version = "0.85.3.dev0"
3
+ version = "0.86.0.dev0"
4
4
  description = "Display Google Ads in Flet apps."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Flet contributors", email = "hello@flet.dev" }]
7
7
  license = "Apache-2.0"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
- "flet==0.85.3.dev0",
10
+ "flet==0.86.0.dev0",
11
11
  ]
12
12
 
13
13
  [project.urls]
@@ -0,0 +1,29 @@
1
+ from flet_ads.banner_ad import BannerAd
2
+ from flet_ads.base_ad import BaseAd
3
+ from flet_ads.consent_manager import ConsentManager
4
+ from flet_ads.interstitial_ad import InterstitialAd
5
+ from flet_ads.types import (
6
+ AdRequest,
7
+ ConsentDebugSettings,
8
+ ConsentRequestParameters,
9
+ ConsentStatus,
10
+ DebugGeography,
11
+ PaidAdEvent,
12
+ PrecisionType,
13
+ PrivacyOptionsRequirementStatus,
14
+ )
15
+
16
+ __all__ = [
17
+ "AdRequest",
18
+ "BannerAd",
19
+ "BaseAd",
20
+ "ConsentDebugSettings",
21
+ "ConsentManager",
22
+ "ConsentRequestParameters",
23
+ "ConsentStatus",
24
+ "DebugGeography",
25
+ "InterstitialAd",
26
+ "PaidAdEvent",
27
+ "PrecisionType",
28
+ "PrivacyOptionsRequirementStatus",
29
+ ]
@@ -66,7 +66,8 @@ class BaseAd(ft.BaseControl):
66
66
  Called when this ad is clicked.
67
67
  """
68
68
 
69
- def before_update(self):
69
+ def init(self):
70
+ super().init()
70
71
  if self.page.web or not self.page.platform.is_mobile():
71
72
  raise ft.FletUnsupportedPlatformException(
72
73
  f"{self.__class__.__name__} is only supported on "
@@ -0,0 +1,136 @@
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")
@@ -27,7 +27,7 @@ class NativeAd(BannerAd):
27
27
  ValueError: When neither :attr:`factory_id` nor `template_style` is set.
28
28
  """
29
29
 
30
- def before_update(self):
31
- super().before_update()
30
+ def init(self):
31
+ super().init()
32
32
  if self.factory_id is None and self.template_style is None:
33
33
  raise ValueError("factory_id or template_style must be set")
@@ -0,0 +1,265 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import Optional
4
+
5
+ import flet as ft
6
+
7
+ __all__ = [
8
+ "AdRequest",
9
+ "ConsentDebugSettings",
10
+ "ConsentRequestParameters",
11
+ "ConsentStatus",
12
+ "DebugGeography",
13
+ "NativeAdTemplateStyle",
14
+ "NativeAdTemplateTextStyle",
15
+ "NativeAdTemplateType",
16
+ "NativeTemplateFontStyle",
17
+ "PaidAdEvent",
18
+ "PrecisionType",
19
+ "PrivacyOptionsRequirementStatus",
20
+ ]
21
+
22
+
23
+ class PrecisionType(Enum):
24
+ """Describes how accurately a paid ad value is reported."""
25
+
26
+ UNKNOWN = "unknown"
27
+ """An ad value with unknown precision."""
28
+
29
+ ESTIMATED = "estimated"
30
+ """An ad value estimated from aggregated data."""
31
+
32
+ PUBLISHER_PROVIDED = "publisherProvided"
33
+ """A publisher-provided ad value, such as manual CPMs in a mediation group."""
34
+
35
+ PRECISE = "precise"
36
+ """The precise value paid for this ad."""
37
+
38
+
39
+ @dataclass
40
+ class PaidAdEvent(ft.Event[ft.EventControlType]):
41
+ """
42
+ Event data for paid ad events.
43
+ """
44
+
45
+ value: float
46
+ """
47
+ The monetary value of the ad.
48
+ """
49
+
50
+ precision: PrecisionType
51
+ """
52
+ The precision of the ad value.
53
+ """
54
+
55
+ currency_code: str
56
+ """
57
+ The currency code of the ad value.
58
+ """
59
+
60
+
61
+ @ft.value
62
+ class AdRequest:
63
+ """
64
+ Targeting info per the AdMob API.
65
+
66
+ This class's properties mirror the native AdRequest API. See for example:
67
+ [AdRequest.Builder for Android](https://developers.google.com/android/reference/com/google/android/gms/ads/AdRequest.Builder).
68
+ """
69
+
70
+ keywords: Optional[list[str]] = None
71
+ """
72
+ Words or phrases describing the current user activity.
73
+ """
74
+
75
+ content_url: Optional[str] = None
76
+ """
77
+ URL string for a webpage whose content matches the app’s primary content.
78
+
79
+ This webpage content is used for targeting and brand safety purposes.
80
+ """
81
+
82
+ neighboring_content_urls: Optional[list[str]] = None
83
+ """
84
+ URLs representing web content near an ad.
85
+ """
86
+
87
+ non_personalized_ads: Optional[bool] = None
88
+ """
89
+ Non-personalized ads are ads that are not based on a user’s past behavior.
90
+
91
+ For more information: https://support.google.com/admob/answer/7676680?hl=en
92
+ """
93
+
94
+ http_timeout: Optional[int] = None
95
+ """
96
+ A custom timeout (in milliseconds) for HTTPS calls during an ad request.
97
+
98
+ Note:
99
+ This is only supported in Android. (ignored on iOS)
100
+ """
101
+
102
+ extras: Optional[dict[str, str]] = None
103
+ """
104
+ Extras to pass to the AdMob adapter.
105
+ """
106
+
107
+
108
+ class NativeAdTemplateType(Enum):
109
+ SMALL = "small"
110
+ MEDIUM = "medium"
111
+
112
+
113
+ class NativeTemplateFontStyle(Enum):
114
+ NORMAL = "normal"
115
+ BOLD = "bold"
116
+ ITALIC = "italic"
117
+ MONOSPACE = "monospace"
118
+
119
+
120
+ @ft.value
121
+ class NativeAdTemplateTextStyle:
122
+ size: Optional[ft.Number] = None
123
+ text_color: Optional[ft.ColorValue] = None
124
+ bgcolor: Optional[ft.ColorValue] = None
125
+ style: Optional[NativeTemplateFontStyle] = None
126
+
127
+
128
+ @ft.value
129
+ class NativeAdTemplateStyle:
130
+ template_type: NativeAdTemplateType = NativeAdTemplateType.MEDIUM
131
+ main_bgcolor: Optional[ft.ColorValue] = None
132
+ corner_radius: Optional[ft.Number] = None
133
+ call_to_action_text_style: Optional[NativeAdTemplateTextStyle] = None
134
+ primary_text_style: Optional[NativeAdTemplateTextStyle] = None
135
+ secondary_text_style: Optional[NativeAdTemplateTextStyle] = None
136
+ tertiary_text_style: Optional[NativeAdTemplateTextStyle] = None
137
+
138
+
139
+ class ConsentStatus(Enum):
140
+ """
141
+ The state of the consent-gathering process, as reported by the
142
+ User Messaging Platform (UMP).
143
+
144
+ Note:
145
+ This describes whether a consent decision has been *collected* — not
146
+ what the user chose. It is never "granted" versus "denied": the user's
147
+ actual selections live in the IAB TCF consent string, which the ads SDK reads
148
+ automatically. Use :meth:`flet_ads.ConsentManager.can_request_ads` to decide
149
+ whether to request ads.
150
+ """
151
+
152
+ NOT_REQUIRED = "notRequired"
153
+ """Consent is not required (e.g. the user is outside a regulated region)."""
154
+
155
+ OBTAINED = "obtained"
156
+ """
157
+ A consent decision has been collected.
158
+
159
+ Set once the user completes the form — whether they consented, declined
160
+ ("Do not consent"), or saved custom choices. This does **not** imply that
161
+ consent was granted.
162
+ """
163
+
164
+ REQUIRED = "required"
165
+ """Consent is required but has not yet been collected."""
166
+
167
+ UNKNOWN = "unknown"
168
+ """Consent status is unknown."""
169
+
170
+
171
+ class PrivacyOptionsRequirementStatus(Enum):
172
+ """
173
+ Whether your app must show a privacy options entry point: a persistent
174
+ control (for example, a button in a settings menu) that lets the user
175
+ change or withdraw their consent at any time after their initial choice.
176
+
177
+ Note:
178
+ Some regulations (e.g. GDPR) require this ongoing entry point.
179
+ When the user triggers it, call
180
+ :meth:`flet_ads.ConsentManager.show_privacy_options_form`.
181
+ """
182
+
183
+ NOT_REQUIRED = "notRequired"
184
+ """A privacy options entry point is not required."""
185
+
186
+ REQUIRED = "required"
187
+ """A privacy options entry point must be shown."""
188
+
189
+ UNKNOWN = "unknown"
190
+ """
191
+ The requirement status is unknown — for example, before
192
+ :meth:`flet_ads.ConsentManager.request_consent_info_update` completes.
193
+ """
194
+
195
+
196
+ class DebugGeography(Enum):
197
+ """
198
+ Debug geography values used to test consent flows.
199
+
200
+ Note:
201
+ These only take effect on devices registered as test devices through
202
+ :attr:`flet_ads.ConsentDebugSettings.test_identifiers`.
203
+ """
204
+
205
+ DISABLED = "disabled"
206
+ """Debug geography disabled."""
207
+
208
+ EEA = "eea"
209
+ """Geography appears as in the EEA (European Economic Area) for debug devices."""
210
+
211
+ REGULATED_US_STATE = "regulatedUsState"
212
+ """Geography appears as in a regulated US State for debug devices."""
213
+
214
+ OTHER = "other"
215
+ """Geography appears as in a region with no regulation in force."""
216
+
217
+
218
+ @ft.value
219
+ class ConsentDebugSettings:
220
+ """
221
+ Debug settings to hardcode in consent requests, useful for testing the
222
+ consent flow during development.
223
+ """
224
+
225
+ debug_geography: Optional[DebugGeography] = None
226
+ """
227
+ The geography to simulate when gathering consent on test devices.
228
+ """
229
+
230
+ test_identifiers: Optional[list[str]] = None
231
+ """
232
+ A list of device identifiers for which debug features
233
+ (such as :attr:`debug_geography`) are enabled.
234
+
235
+ Note:
236
+ Simulators and emulators are automatically registered as test devices,
237
+ so this is only needed for physical devices.
238
+
239
+ A physical device's hashed ID is printed to the **native** device log
240
+ (Xcode console/Console.app on iOS, `adb logcat` on Android)
241
+ the first time a consent request is made from it.
242
+ """
243
+
244
+
245
+ @ft.value
246
+ class ConsentRequestParameters:
247
+ """
248
+ Parameters sent when updating the user's consent information.
249
+ """
250
+
251
+ tag_for_under_age_of_consent: Optional[bool] = None
252
+ """
253
+ Whether the user is tagged as being under the age of consent.
254
+
255
+ `False` means users are not under the age of consent.
256
+
257
+ Warning:
258
+ When `True`, the consent form is not shown, as users under the age of
259
+ consent cannot be asked to provide consent.
260
+ """
261
+
262
+ consent_debug_settings: Optional[ConsentDebugSettings] = None
263
+ """
264
+ Debug settings to hardcode in test requests.
265
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-ads
3
- Version: 0.85.3.dev0
3
+ Version: 0.86.0.dev0
4
4
  Summary: Display Google Ads in Flet apps.
5
5
  Author-email: Flet contributors <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -11,7 +11,7 @@ Project-URL: Issues, https://github.com/flet-dev/flet/issues
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: flet==0.85.3.dev0
14
+ Requires-Dist: flet==0.86.0.dev0
15
15
  Dynamic: license-file
16
16
 
17
17
  # flet-ads
@@ -4,6 +4,7 @@ pyproject.toml
4
4
  src/flet_ads/__init__.py
5
5
  src/flet_ads/banner_ad.py
6
6
  src/flet_ads/base_ad.py
7
+ src/flet_ads/consent_manager.py
7
8
  src/flet_ads/interstitial_ad.py
8
9
  src/flet_ads/native_ad.py
9
10
  src/flet_ads/types.py
@@ -15,8 +16,10 @@ src/flet_ads.egg-info/top_level.txt
15
16
  src/flutter/flet_ads/pubspec.yaml
16
17
  src/flutter/flet_ads/lib/flet_ads.dart
17
18
  src/flutter/flet_ads/lib/src/banner.dart
19
+ src/flutter/flet_ads/lib/src/consent_manager.dart
18
20
  src/flutter/flet_ads/lib/src/extension.dart
19
21
  src/flutter/flet_ads/lib/src/interstitial.dart
20
22
  src/flutter/flet_ads/lib/src/native.dart
21
23
  src/flutter/flet_ads/lib/utils/ads.dart
24
+ src/flutter/flet_ads/lib/utils/consent.dart
22
25
  src/flutter/flet_ads/lib/utils/native.dart
@@ -0,0 +1 @@
1
+ flet==0.86.0.dev0
@@ -0,0 +1,92 @@
1
+ import 'dart:async';
2
+
3
+ import 'package:flet/flet.dart';
4
+ import 'package:flutter/foundation.dart';
5
+ import 'package:google_mobile_ads/google_mobile_ads.dart';
6
+
7
+ import '../utils/consent.dart';
8
+
9
+ class ConsentManagerService extends FletService {
10
+ ConsentManagerService({required super.control});
11
+
12
+ @override
13
+ void init() {
14
+ super.init();
15
+ debugPrint("ConsentManager(${control.id}).init");
16
+ control.addInvokeMethodListener(_invokeMethod);
17
+ }
18
+
19
+ Future<dynamic> _invokeMethod(String name, dynamic args) async {
20
+ debugPrint("ConsentManager.$name($args)");
21
+ switch (name) {
22
+ case "request_consent_info_update":
23
+ final completer = Completer<void>();
24
+ ConsentInformation.instance.requestConsentInfoUpdate(
25
+ parseConsentRequestParameters(args?["params"]),
26
+ () {
27
+ if (!completer.isCompleted) completer.complete();
28
+ },
29
+ (FormError error) {
30
+ if (!completer.isCompleted) {
31
+ completer.completeError(Exception(
32
+ "Consent info update failed (${error.errorCode}): ${error.message}"));
33
+ }
34
+ },
35
+ );
36
+ return completer.future;
37
+
38
+ case "is_consent_form_available":
39
+ return await ConsentInformation.instance.isConsentFormAvailable();
40
+
41
+ case "get_consent_status":
42
+ return (await ConsentInformation.instance.getConsentStatus()).name;
43
+
44
+ case "can_request_ads":
45
+ return await ConsentInformation.instance.canRequestAds();
46
+
47
+ case "get_privacy_options_requirement_status":
48
+ return (await ConsentInformation.instance
49
+ .getPrivacyOptionsRequirementStatus())
50
+ .name;
51
+
52
+ case "load_and_show_consent_form_if_required":
53
+ final completer = Completer<void>();
54
+ ConsentForm.loadAndShowConsentFormIfRequired((FormError? error) {
55
+ if (completer.isCompleted) return;
56
+ if (error != null) {
57
+ completer.completeError(Exception(
58
+ "Consent form error (${error.errorCode}): ${error.message}"));
59
+ } else {
60
+ completer.complete();
61
+ }
62
+ });
63
+ return completer.future;
64
+
65
+ case "show_privacy_options_form":
66
+ final completer = Completer<void>();
67
+ ConsentForm.showPrivacyOptionsForm((FormError? error) {
68
+ if (completer.isCompleted) return;
69
+ if (error != null) {
70
+ completer.completeError(Exception(
71
+ "Privacy options form error (${error.errorCode}): ${error.message}"));
72
+ } else {
73
+ completer.complete();
74
+ }
75
+ });
76
+ return completer.future;
77
+
78
+ case "reset":
79
+ return await ConsentInformation.instance.reset();
80
+
81
+ default:
82
+ throw Exception("Unknown ConsentManager method: $name");
83
+ }
84
+ }
85
+
86
+ @override
87
+ void dispose() {
88
+ debugPrint("ConsentManager(${control.id}).dispose()");
89
+ control.removeInvokeMethodListener(_invokeMethod);
90
+ super.dispose();
91
+ }
92
+ }
@@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
3
3
  import 'package:google_mobile_ads/google_mobile_ads.dart';
4
4
 
5
5
  import 'banner.dart';
6
+ import 'consent_manager.dart';
6
7
  import 'interstitial.dart';
7
8
 
8
9
  class Extension extends FletExtension {
@@ -18,6 +19,8 @@ class Extension extends FletExtension {
18
19
  switch (control.type) {
19
20
  case "InterstitialAd":
20
21
  return InterstitialAdService(control: control);
22
+ case "ConsentManager":
23
+ return ConsentManagerService(control: control);
21
24
  default:
22
25
  return null;
23
26
  }
@@ -0,0 +1,25 @@
1
+ import 'package:flet/flet.dart';
2
+ import 'package:google_mobile_ads/google_mobile_ads.dart';
3
+
4
+ DebugGeography? parseDebugGeography(String? value,
5
+ [DebugGeography? defaultValue]) =>
6
+ parseEnum(DebugGeography.values, "debugGeography$value", defaultValue);
7
+
8
+ ConsentDebugSettings? parseConsentDebugSettings(dynamic value,
9
+ [ConsentDebugSettings? defaultValue]) {
10
+ if (value == null) return defaultValue;
11
+ return ConsentDebugSettings(
12
+ debugGeography: parseDebugGeography(value["debug_geography"]),
13
+ testIdentifiers:
14
+ (value["test_identifiers"] as List?)?.map((e) => e.toString()).toList(),
15
+ );
16
+ }
17
+
18
+ ConsentRequestParameters parseConsentRequestParameters(dynamic value) {
19
+ if (value == null) return ConsentRequestParameters();
20
+ return ConsentRequestParameters(
21
+ tagForUnderAgeOfConsent: value["tag_for_under_age_of_consent"],
22
+ consentDebugSettings:
23
+ parseConsentDebugSettings(value["consent_debug_settings"]),
24
+ );
25
+ }
@@ -12,7 +12,7 @@ dependencies:
12
12
  sdk: flutter
13
13
 
14
14
  collection: ^1.16.0
15
- google_mobile_ads: ^8.0.0
15
+ google_mobile_ads: ^9.0.0
16
16
 
17
17
  flet:
18
18
  path: ../../../../../../../packages/flet
@@ -1,17 +0,0 @@
1
- from flet_ads.banner_ad import BannerAd
2
- from flet_ads.base_ad import BaseAd
3
- from flet_ads.interstitial_ad import InterstitialAd
4
- from flet_ads.types import (
5
- AdRequest,
6
- PaidAdEvent,
7
- PrecisionType,
8
- )
9
-
10
- __all__ = [
11
- "AdRequest",
12
- "BannerAd",
13
- "BaseAd",
14
- "InterstitialAd",
15
- "PaidAdEvent",
16
- "PrecisionType",
17
- ]
@@ -1,131 +0,0 @@
1
- from dataclasses import dataclass
2
- from enum import Enum
3
- from typing import Optional
4
-
5
- import flet as ft
6
-
7
- __all__ = [
8
- "AdRequest",
9
- "NativeAdTemplateStyle",
10
- "NativeAdTemplateTextStyle",
11
- "NativeAdTemplateType",
12
- "NativeTemplateFontStyle",
13
- "PaidAdEvent",
14
- "PrecisionType",
15
- ]
16
-
17
-
18
- class PrecisionType(Enum):
19
- """Describes how accurately a paid ad value is reported."""
20
-
21
- UNKNOWN = "unknown"
22
- """An ad value with unknown precision."""
23
-
24
- ESTIMATED = "estimated"
25
- """An ad value estimated from aggregated data."""
26
-
27
- PUBLISHER_PROVIDED = "publisherProvided"
28
- """A publisher-provided ad value, such as manual CPMs in a mediation group."""
29
-
30
- PRECISE = "precise"
31
- """The precise value paid for this ad."""
32
-
33
-
34
- @dataclass
35
- class PaidAdEvent(ft.Event[ft.EventControlType]):
36
- """
37
- Event data for paid ad events.
38
- """
39
-
40
- value: float
41
- """
42
- The monetary value of the ad.
43
- """
44
-
45
- precision: PrecisionType
46
- """
47
- The precision of the ad value.
48
- """
49
-
50
- currency_code: str
51
- """
52
- The currency code of the ad value.
53
- """
54
-
55
-
56
- @ft.value
57
- class AdRequest:
58
- """
59
- Targeting info per the AdMob API.
60
-
61
- This class's properties mirror the native AdRequest API. See for example:
62
- [AdRequest.Builder for Android](https://developers.google.com/android/reference/com/google/android/gms/ads/AdRequest.Builder).
63
- """
64
-
65
- keywords: Optional[list[str]] = None
66
- """
67
- Words or phrases describing the current user activity.
68
- """
69
-
70
- content_url: Optional[str] = None
71
- """
72
- URL string for a webpage whose content matches the app’s primary content.
73
-
74
- This webpage content is used for targeting and brand safety purposes.
75
- """
76
-
77
- neighboring_content_urls: Optional[list[str]] = None
78
- """
79
- URLs representing web content near an ad.
80
- """
81
-
82
- non_personalized_ads: Optional[bool] = None
83
- """
84
- Non-personalized ads are ads that are not based on a user’s past behavior.
85
-
86
- For more information: https://support.google.com/admob/answer/7676680?hl=en
87
- """
88
-
89
- http_timeout: Optional[int] = None
90
- """
91
- A custom timeout (in milliseconds) for HTTPS calls during an ad request.
92
-
93
- Note:
94
- This is only supported in Android. (ignored on iOS)
95
- """
96
-
97
- extras: Optional[dict[str, str]] = None
98
- """
99
- Extras to pass to the AdMob adapter.
100
- """
101
-
102
-
103
- class NativeAdTemplateType(Enum):
104
- SMALL = "small"
105
- MEDIUM = "medium"
106
-
107
-
108
- class NativeTemplateFontStyle(Enum):
109
- NORMAL = "normal"
110
- BOLD = "bold"
111
- ITALIC = "italic"
112
- MONOSPACE = "monospace"
113
-
114
-
115
- @ft.value
116
- class NativeAdTemplateTextStyle:
117
- size: Optional[ft.Number] = None
118
- text_color: Optional[ft.ColorValue] = None
119
- bgcolor: Optional[ft.ColorValue] = None
120
- style: Optional[NativeTemplateFontStyle] = None
121
-
122
-
123
- @ft.value
124
- class NativeAdTemplateStyle:
125
- template_type: NativeAdTemplateType = NativeAdTemplateType.MEDIUM
126
- main_bgcolor: Optional[ft.ColorValue] = None
127
- corner_radius: Optional[ft.Number] = None
128
- call_to_action_text_style: Optional[NativeAdTemplateTextStyle] = None
129
- primary_text_style: Optional[NativeAdTemplateTextStyle] = None
130
- secondary_text_style: Optional[NativeAdTemplateTextStyle] = None
131
- tertiary_text_style: Optional[NativeAdTemplateTextStyle] = None
@@ -1 +0,0 @@
1
- flet==0.85.3.dev0
File without changes
File without changes
File without changes