skip to content

When filling Google Play's Data safety form and Apple's App Privacy details for a Flutter app, why audit plugins rather than just your Dart code?

level: middleimportance: should knowfreq 32%

answer

  1. declarations cover bundled third-party code
  2. plugins wrap native SDKs
  3. transitive dependencies count too
  4. flutter pub deps as the inventory
  5. forms, policy and behaviour must agree

basics

~20 s

Both forms must declare data collected by everything in the binary, including third-party SDKs. Flutter plugins wrap native SDKs that collect data your Dart code never touches, so the inventory starts from the full dependency tree, not your own calls.

solid answer

~40 s

Google Play's **Data safety** section and Apple's **App Privacy** details describe what the whole app collects and shares, and both stores hold the developer responsible for code from third-party SDKs bundled in it. In Flutter much of that code arrives through plugins: `firebase_analytics` pulls in the native analytics SDK, a crash reporter, an ads or attribution plugin, each collecting identifiers or diagnostics with no Dart call of yours involved. So the audit starts from `flutter pub deps --no-dev`, including transitive plugins, then each plugin's native dependencies and its vendor's disclosure. The answers must match the privacy policy and the app's real behaviour; a mismatch found in review or later is grounds for rejection or removal, and a new plugin means revisiting both forms.

code

bash · 1 line
bash
flutter pub deps --no-dev --style=compact

go deeper

for a junior

Recall that both privacy forms cover everything in the binary, including SDKs that plugins bring in.

for a middle

Explain how to inventory the release dependency tree, find the native SDKs behind plugins and map their collection to the forms.

for a senior

Show you tie the forms to the dependency-upgrade process and cross-check them with the privacy policy and consent flow.

for a principal

Weigh each SDK's data cost against its value and set a policy for which plugins may enter the app at all.

## What the two forms are Both stores make you publish a structured summary of the app's data practices next to the listing: | Store | Form | What it asks | |---|---|---| | Google Play | **Data safety** section (Play Console, App content) | which data types are collected or shared, for what purposes, whether collection is optional, encryption in transit, how deletion works | | App Store | **App Privacy** details (App Store Connect) | which data types are collected, whether they are linked to the user's identity, whether they are used for tracking | The key rule for a Flutter developer: **the answers cover the whole binary**, including SDKs from third parties. "My Dart code never reads the device identifier" is not a defence if a bundled SDK does. ## Why Flutter makes this easy to get wrong A Flutter plugin is Dart API on top of platform code, and that platform code frequently **wraps a vendor's native SDK**. When you add one line to `pubspec.yaml`, you may be shipping: - an analytics SDK that records app-instance identifiers and usage events as soon as it initialises; - a crash reporter that uploads device model, OS version and stack traces; - an ads or attribution SDK that reads an advertising identifier; - networking or media plugins that are harmless on their own but pull in further native libraries. None of this appears in your Dart code, and some arrives **transitively**, through a plugin that depends on another plugin. A developer who fills in the forms by reading `lib/` will under-declare. ## How to run the audit 1. **List every dependency the release ships.** `flutter pub deps --no-dev --style=compact` prints the resolved tree without dev dependencies, including transitive packages. 2. **Separate plugins from pure Dart packages.** Plugins have `android/` or `ios/`/`darwin/` folders; those are where native SDKs come in. 3. **Read each plugin's native dependencies** in its Gradle file and its CocoaPods or Swift Package manifest, then read the SDK vendor's own data-disclosure guidance. 4. **Map what each collects** to the forms' data types and purposes, alongside what your own backend collects through the app. 5. **Cross-check** the answers with the privacy policy URL on the listing and with actual behaviour, such as whether collection starts before consent. ## A worked example Imagine a Flutter pharmacy app whose `pubspec.yaml` lists `firebase_core`, `firebase_analytics`, `firebase_crashlytics`, `camera` and `http`: - `http` is a pure Dart package; it collects nothing on its own, but what your code sends through it, such as account details, still belongs on the forms. - `camera` accesses the camera; if photos of prescriptions are uploaded, that is user content you collect. - `firebase_analytics` and `firebase_crashlytics` wrap native SDKs that gather identifiers, usage and diagnostics once initialised, whether or not you ever call `logEvent`. - `firebase_core` pulls in native Firebase dependencies that the other plugins build on. A form filled in from the Dart code alone would list the account data and perhaps the photos, and miss everything the two Firebase SDKs collect. ## Keeping the forms true - Revisit both forms whenever a plugin is **added, removed or upgraded**; an SDK's new version can add collection. - Remember per-platform differences: a plugin may use a different SDK on Android and iOS, so the two forms need not be identical. - The Apple side also involves **privacy manifests** bundled with SDKs; that file-level mechanism is a separate subject from the App Privacy answers. - If you gate an SDK behind consent in Dart, the declaration still describes what happens once consent is given. ## What goes wrong when it is not done A form that disagrees with what the app does is a policy violation. It can surface as a review rejection, a later enforcement notice or a removal until corrected. Getting it right once is not enough: the declarations describe the binary, so each release that changes dependencies is a moment to re-check them.

  • Your Flutter app starts Firebase Analytics only after the user consents. Can the Data safety form say the app collects nothing?
    No. The forms describe what the app collects when it runs as shipped, and consent-gated collection is still collection. Declare the data types the SDK gathers once enabled; Play lets you mark collection as optional where users can decline it. Consent changes how you answer, not whether you answer.
  • A plugin upgrade in a Flutter app adds a new native SDK dependency. What release step should that trigger?
    Re-run the dependency audit for that plugin: read the new native dependency, check what data it collects, and update the Data safety and App Privacy answers before submitting. Also check the merged Android manifest, since the same upgrade can bring new permissions.

saying these in an interview costs you the question

  • Only data my own Dart code sends needs to be declared.
  • Plugins are open source, so their data collection does not count.
  • Dev dependencies must be declared because they appear in pubspec.yaml.
  • The Android and iOS answers must be identical for a Flutter app.
  • Consent-gated SDKs can be left off the forms entirely.