-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathllms.txt
More file actions
49 lines (36 loc) · 6.56 KB
/
Copy pathllms.txt
File metadata and controls
49 lines (36 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# age_range_signals
> Flutter plugin for age verification and age gating. Wraps the Google Play Age Signals API on Android and Apple's DeclaredAgeRange API on iOS 26+, returning an age range plus how much assurance backs it. It reports signals the OS already holds: it is not identity verification, document scanning, or KYC, and it never returns a date of birth.
Import only `package:age_range_signals/age_range_signals.dart` and use the singleton `AgeRangeSignals.instance`. The `age_range_signals_method_channel` and `age_range_signals_platform_interface` libraries are federated-plugin plumbing; calling `AgeRangeSignalsPlatform.instance` directly skips the public wrapper's argument validation. Subclass it only to stub the plugin in tests.
Since 0.8.0 the flow has two calls. Request access first, then read signals only if access was granted:
```dart
await AgeRangeSignals.instance.initialize(ageGates: [13, 16, 18]);
final access = await AgeRangeSignals.instance.requestAgeSignalsAccess();
if (access == AgeSignalsAccessStatus.shared) {
final result = await AgeRangeSignals.instance.checkAgeSignals();
}
```
Constraints that are easy to get wrong:
- **Call `initialize()` on both platforms.** iOS requires `ageGates` and throws `NotInitializedException` without them. Play ignores gates, but the plugin uses your highest gate as the bar for `verified`, using 18 until you supply them, so skipping it on Android silently changes the verdict. A later `initialize()` that omits gates keeps the ones you already set. Apple accepts 1 to 3 gates at least 2 years apart, so `[13, 16, 18]` is valid and `[13, 14]` is rejected by the OS.
- **`status` is the verdict, `ageRangeSource` is the assurance.** `verified` means the reported band starts at or above your highest gate; `supervised` means it falls below. Both platforms apply the same rule. Any tier can reach either value.
- **Gates off a band edge quantise upward on Android.** Play reports fixed bands (0-12, 13-15, 16-17, 18+); iOS buckets against your actual gates. With a gate at 15, a 15-year-old is `verified` on iOS but `supervised` on Android. Prefer 13, 16 or 18.
- **A tier is never proof of age.** `tierD` means an ID was checked, and that ID can read 12. Read `ageRangeSource` only to apply a minimum assurance policy, never as the verdict.
- **`AgeSignalsStatus`**: handle `verified`, `unknown`, `declined`, `supervised`, `supervisedApprovalPending`, `supervisedApprovalDenied`. `declared` still exists but is deprecated and never returned; read `ageRangeSource == AgeRangeSource.tierA` instead. `declined` is iOS only; the two `supervisedApproval*` values are Android only.
- **`AgeSignalsAccessStatus`** is what `requestAgeSignalsAccess()` returns: `shared`, `notShared` (a decline, not an error), `verificationRequired` (send the user to the Play Store; there is no in-app flow), `unknown`. iOS returns `shared`, since Apple gathers consent inside `checkAgeSignals()` itself, but throws `UnsupportedPlatformException` below 26.0 and `NotInitializedException` without gates, so it doubles as a pre-flight there.
- **`AgeRangeSource`** (Android only), weakest to strongest assurance: `tierA` self-declared, `tierB` parent- or guardian-managed, `tierC` assessed via credit card, email, selfie, government ID or tax ID, `tierD` government ID plus selfie or a digital ID.
- **`SignificantChangeStatus`** (Android, supervised users): `approved`, `pending`, `declined`. A pending or declined state reports `supervisedApprovalPending` / `supervisedApprovalDenied` whatever the age, because an outstanding guardian decision is actionable either way.
- **Nullable age bounds.** Null when nothing was shared. A `verified` result always has `ageLower` set. `ageUpper` is null only for Play's open-ended 18+ band, so a lower gate can yield a closed verified band; never use `ageUpper == null` as a proxy for adult. The two `supervisedApproval*` statuses can arrive with no band at all.
- **Android needs an Activity.** The plugin is `ActivityAware` because Play hosts its sharing prompt; without one, `requestAgeSignalsAccess()` throws `ApiErrorException` with `PRESENTATION_CONTEXT_UNAVAILABLE`.
- **Testing.** `useMockData` and `mockData` are Android only, backed by Google's `FakeAgeSignalsManager`, and only work in **debuggable** builds: a release build throws `MockDataNotAllowedException`, because the fake manager forges age signals. They are silently ignored on iOS, which has no testing utility and needs a real device on iOS 26.2+.
- **Platform floors.** Android API 23+ with Google Play services. iOS 26.0 for the base API, 26.2 for regional eligibility, 26.4 for regulatory features. iOS also needs Apple's DeclaredAgeRange entitlement; a missing or unapproved one throws `MissingEntitlementException`.
- **Google Play policy.** Age Signals data may be used only to deliver age-appropriate experiences. Never route it into advertising, marketing, profiling, or analytics. Violations risk API termination and app suspension, so do not log results to an analytics SDK.
Errors all extend `AgeSignalsException`, which carries `code` and a `details` string of platform diagnostics. Subclasses: `ApiNotAvailableException`, `UnsupportedPlatformException`, `NotInitializedException`, `MissingEntitlementException`, `ApiErrorException`, `PlayServicesException`, `NetworkErrorException`, `UserNotSignedInException`, `UserCancelledException`, `MockDataNotAllowedException`.
`AgeSignalsResult` fields: `status`, `ageLower`, `ageUpper`, `ageRangeSource` (Android), `significantChangeStatus` (Android), `significantChangeApprovalDate` (Android; named `mostRecentApprovalDate` before 0.8.0, still available as a deprecated alias), `installId` (Android), `source` (iOS declaration type), `activeParentalControls` (iOS).
## Docs
- [README](https://github.com/zigapovhe/age_range_signals/blob/main/README.md): platform setup, full usage examples, testing, limitations, troubleshooting, and legal compliance
- [API reference](https://pub.dev/documentation/age_range_signals/latest/): generated dartdoc for every public symbol
- [CHANGELOG](https://github.com/zigapovhe/age_range_signals/blob/main/CHANGELOG.md): version-specific behavior, including the 0.8.0 breaking changes and bugs fixed in 0.6.x
## Optional
- [Example app](https://github.com/zigapovhe/age_range_signals/blob/main/example/lib/main.dart): runnable demo covering both platforms, the two-call access flow, and the regulatory features UI
- [pub.dev package](https://pub.dev/packages/age_range_signals)
- [Google Play Age Signals API](https://developer.android.com/google/play/age-signals)
- [Apple DeclaredAgeRange](https://developer.apple.com/documentation/declaredagerange)