tolinku 0.6.2
tolinku: ^0.6.2 copied to clipboard
Tolinku SDK for deep linking, analytics, referrals, and in-app messages.
import 'package:flutter/material.dart';
import 'package:tolinku/tolinku.dart';
/// Minimal integration, and the build target CI uses to compile the native side.
///
/// The package ships Kotlin on Android to read the Play Install Referrer and
/// Swift on iOS to report the timezone. Neither is exercised by `flutter test`,
/// which runs Dart on the host, so an app that actually builds for both is the
/// only way a mistake in either shows up before a user hits it.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Tolinku.configure(apiKey: 'tolk_pub_your_key');
await _reportPlatformSignals();
runApp(const ExampleApp());
}
/// Prints what the native side reports, which is how CI knows the plugin is
/// not merely present but answering.
///
/// A build can only show that the plugin was linked in. Whether it is
/// registered and replying is a different question, and an important one here,
/// because Swift Package Manager and CocoaPods register plugins by different
/// routes. [readPlatformSignals] never throws, so an unregistered plugin
/// returns exactly what a device with nothing to report returns, and only
/// looking at the values can tell those apart.
///
/// This prints rather than asserts because print reaches the device log, which
/// a CI machine can read from outside the app without a debug connection.
Future<void> _reportPlatformSignals() async {
final signals = await readPlatformSignals();
// Read by .github/workflows/ci.yml. Keep the prefix and shape in step.
print(
'TOLINKU_SIGNALS timezone=${signals.timezone ?? ''} '
'os_version=${signals.osVersion ?? ''}',
);
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _status = 'Not claimed yet';
@override
void initState() {
super.initState();
_claim();
}
/// Call once on the first launch after install.
///
/// Tries the Play Install Referrer, then falls back to device signals, which
/// are the only mechanism on iOS. Both are collected by the SDK.
Future<void> _claim() async {
try {
final link = await Tolinku.instance.deferred.claimDeferredLink(
appspaceId: 'YOUR_APPSPACE_ID',
);
if (!mounted) return;
setState(() {
_status = link == null
? 'Nothing waiting for this device'
: 'Claimed ${link.deepLinkPath}';
});
} on TolinkuException catch (e) {
// A 403 here means the Appspace ID is wrong, which is worth seeing rather
// than swallowing. A first launch should not fail on it either.
if (!mounted) return;
setState(() => _status = 'Claim failed: ${e.message}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Tolinku')),
body: Center(child: Text(_status)),
);
}
}