Docs

Flutter SDK 3.0

What changes when you move the Grovs Flutter plugin from 1.x to 3.0

3.0.0 is a major release of grovs_flutter_plugin. Every Dart method, stream, and type from 1.1.0 is still present with the same signature; the only signature change is that GenerateLinkParams gained two optional named parameters, copyToClipboardIos and copyToClipboardAndroid. The native config keys you already have in Info.plist and AndroidManifest.xml keep their names. What changes is what runs underneath: the plugin now pins the native 3.0 SDKs (Grovs ~> 3.0 on iOS, io.grovs:Grovs:3.0.0 on Android), so clipboard-assisted deferred deep linking runs on the first launch, consent can be gated from the config files, and analytics is available. Most apps upgrade by bumping the version and deciding how they gate on consent.

Requirements are unchanged from 1.1.0: Flutter 3.3.0, Dart 3.9.2, Android 7.0 (API 24). iOS 13.0 is the minimum for 3.0.0.

There is no 2.x. The plugin goes from 1.1.0 straight to 3.0.0 so that it shares a major version with the native SDKs it wraps.

Checklist

  1. Bump the dependency to 3.0.0 and refresh the native pods.
  2. Review your consent gating if you have a consent flow: start disabled through GrovsEnabled / grovs_enabled and call the new setSDK(true).
  3. Decide on screen tracking. Nothing is tracked until you add Grovs.navigatorObserver.
  4. Check the other behavior changes: the clipboard read, startDate on custom purchases, and your store privacy declarations.

1. Bump the version

In pubspec.yaml:

YAML
dependencies:
  grovs_flutter_plugin: ^3.0.0

Then run flutter pub get. On iOS the plugin's podspec now requires Grovs ~> 3.0 instead of ~> 2.3; if CocoaPods reports that it cannot find a matching version, refresh the specs:

Bash
cd ios && pod install --repo-update

On Android the plugin pulls in io.grovs:Grovs:3.0.0 in place of 1.1.1 through Gradle, with no changes on your side.

setSDK is new. 1.x had no way to stop collection from Dart. In 3.0, setSDK(false) stops everything the native SDK does: no authentication, device lookup, clipboard read, events, screen views, or purchases. The plugin also drops deep links while disabled. setSDK(true) starts collection again and replays the link that launched the app while disabled.

Start disabled through the config files. The plugin configures the native SDK at launch, before main() runs, so calling setSDK(false) from Dart cannot prevent that first round of startup work. If you gate on consent, add the key and enable after consent:

XML
<!-- Info.plist -->
<key>GrovsEnabled</key>
<false/>
XML
<!-- AndroidManifest.xml, inside <application> -->
<meta-data
    android:name="grovs_enabled"
    android:value="false" />
Dart
// 3.0: on every launch, after restoring the stored decision
if (await ConsentStore.hasConsent()) {
  await Grovs().setSDK(true);
}

The value is not persisted, so store it yourself and call setSDK(true) on every launch where consent exists. See Privacy & Consent.

3. Decide on screen tracking

The native 3.0 SDKs track screens automatically by default, but the plugin turns that off on both platforms so the Flutter host view is not reported and Flutter routes are not double-counted. An app that only bumps the version therefore sends no screen views, the same as on 1.x.

To start tracking Flutter routes, add the observer:

Dart
MaterialApp(
  navigatorObservers: [Grovs.navigatorObserver],
  // ...
);

Screen names come from RouteSettings.name; unnamed routes fall back to the route's runtime type, which is obfuscated in release builds. See Events & Screen Tracking for what is tracked, how names are chosen, and how to alias them.

4. Check the other behavior changes

Clipboard-assisted deferred deep linking is on. On the first launch after install, the native SDK may read the clipboard to attribute the install to a copy-to-clipboard link, and iOS may show its system paste notice. This only happens when the backend reports recent clicks on copy-to-clipboard links for your project and the clipboard holds a web URL. If you never enable copy-to-clipboard for your project or its links, the clipboard is never read. Starting the SDK disabled prevents it too. See Clipboard-assisted deferred deep linking.

startDate on logCustomPurchase is now forwarded. In 1.x the value was ignored and the native SDK used the current time. In 3.0 it is sent as milliseconds since the epoch and honored on both platforms, so a purchase you back-date now carries the date you pass.

Android configures once per process. The native SDK is configured when the first Flutter engine attaches and not again for later engines. Consent state is shared by all engines.

iOS drops an in-flight lookup on disable. A deep link lookup that was in progress when setSDK(false) was called is dropped by the plugin. If consent is granted again before it completes, the native SDK may still deliver it.

Update your store privacy declarations. Screen views and custom events are new categories of collection once you use them. Check your App Privacy answers and Data safety form against what the SDK collects.

What's new in 3.0

Nothing here is required:

Verifying the upgrade

Turn on info logging early in main():

Dart
await Grovs().setDebugLevel('info');

Then check that deep links still arrive on onDeeplinkReceived, that setSDK(true) is called on launches where consent exists, and, if you added the observer, that screen views appear in the dashboard under names you recognize. Use setScreenAliases to rename any that read like route types.

See also

Edit this page on GitHubLast updated 2026-09-15