How do you integrate the Genuin Flutter SDK into your application?
The Genuin Flutter SDK enables brands to deliver immersive, scalable, and monetizable community experiences directly within their mobile apps.
- Faster development: Integrate feeds, communities, and groups without building native modules from scratch
- Consistent experience: Unified UI/UX across Android and iOS
- Higher engagement: Native vertical video experiences with smooth performance
- Built-in monetization readiness: Supports ad-enabled video surfaces
- Identity & personalization: Deep linking, SSO, and user-level experiences out of the box
Guide — Step-by-step integration
1. Requirements
| Platform | Minimum Version | Language | Orientation | Supported Destinations |
|---|---|---|---|---|
| Android | 24 | Java/Kotlin | Portrait | Mobile |
| iOS | 13.0 | Swift | Portrait | iPhone |
2. Android Setup
Installation
Complete the following configuration steps and insert the provided code snippets into their respective files to integrate the Flutter SDK for Android.
Step 1. Project Configuration: Within android/build.gradle:
allprojects {
repositories {
google()
mavenCentral()
// Add jitpack
maven {
setUrl("https://jitpack.io")
}
}
} Step 2: In android/app/build.gradle:
android {
defaultConfig {
minSdk = 24
}
} Step 3: In android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- 1. Remove android:name attribute
2. Add tools:replace="android:label" -->
<application android:label="genuin_sdk_example" android:icon="@mipmap/ic_launcher"
tools:replace="android:label">
<!-- 1. If you want handle deeplink change launch mode to singleTask
2. Remove android:taskAffinity="" -->
<activity android:name=".MainActivity" android:exported="true"
android:launchMode="singleTask" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest> Step 4: Within android/app/src/main/res/values/styles.xml:
The SDK requires Material Components. To ensure compatibility and avoid runtime issues, you must utilize a Material theme as demonstrated in the following example:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>Step 5: Within android/app/proguard-rules.pro:
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
-keep class com.bumptech.glide.**{*;}
-keep public class * {
public *;
protected *;
}
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn java.lang.reflect.AnnotatedType
-dontwarn com.google.api.client.http.GenericUrl
-dontwarn com.google.api.client.http.HttpHeaders
-dontwarn com.google.api.client.http.HttpRequest
-dontwarn com.google.api.client.http.HttpRequestFactory
-dontwarn com.google.api.client.http.HttpResponse
-dontwarn com.google.api.client.http.HttpTransport
-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
-dontwarn com.google.api.client.http.javanet.NetHttpTransport
-dontwarn com.squareup.picasso.Picasso
-dontwarn com.squareup.picasso.RequestCreator
-dontwarn java.awt.image.BufferedImage
-dontwarn javax.imageio.ImageIO
-dontwarn org.joda.time.Instant
-dontwarn org.junit.Assert
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn org.slf4j.impl.StaticMDCBinder
-dontwarn org.slf4j.impl.StaticMarkerBinder
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.begenuin.begenuin.data.model.** { <fields>; }
-keep class com.begenuin.begenuin.vo.** { <fields>; }
# RenderScript
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class androidx.renderscript.** { *; }
-keepattributes *Annotation*
-keep class com.giphy.sdk.core.models.** { *; }
-keep class com.giphy.sdk.ui.views.** { *; }
-keep public class * implements java.lang.reflect.Type
-keep class com.google.mediapipe.solutioncore.** {*;}
-keep class com.google.protobuf.** {*;}
-dontwarn com.begenuin.sdk.BR
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManagerFactory
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest
-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
-dontwarn com.google.android.play.core.tasks.OnFailureListener
-dontwarn com.google.android.play.core.tasks.OnSuccessListener
-dontwarn com.google.android.play.core.tasks.Task
-dontwarn com.google.mediapipe.proto.CalculatorProfileProto$CalculatorProfile
-dontwarn com.google.mediapipe.proto.GraphTemplateProto$CalculatorGraphTemplate
-dontwarn javax.lang.model.AnnotatedConstruct
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.AnnotationMirror
-dontwarn javax.lang.model.element.AnnotationValue
-dontwarn javax.lang.model.element.AnnotationValueVisitor
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.ElementKind
-dontwarn javax.lang.model.element.ElementVisitor
-dontwarn javax.lang.model.element.ExecutableElement
-dontwarn javax.lang.model.element.Name
-dontwarn javax.lang.model.element.NestingKind
-dontwarn javax.lang.model.element.PackageElement
-dontwarn javax.lang.model.element.QualifiedNameable
-dontwarn javax.lang.model.element.TypeElement
-dontwarn javax.lang.model.element.TypeParameterElement
-dontwarn javax.lang.model.element.VariableElement
-dontwarn javax.lang.model.type.ArrayType
-dontwarn javax.lang.model.type.DeclaredType
-dontwarn javax.lang.model.type.ErrorType
-dontwarn javax.lang.model.type.ExecutableType
-dontwarn javax.lang.model.type.IntersectionType
-dontwarn javax.lang.model.type.NoType
-dontwarn javax.lang.model.type.NullType
-dontwarn javax.lang.model.type.PrimitiveType
-dontwarn javax.lang.model.type.TypeKind
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVariable
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.type.WildcardType
-dontwarn javax.lang.model.util.AbstractElementVisitor8
-dontwarn javax.lang.model.util.ElementFilter
-dontwarn javax.lang.model.util.Elements
-dontwarn javax.lang.model.util.SimpleAnnotationValueVisitor8
-dontwarn javax.lang.model.util.SimpleElementVisitor8
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
-dontwarn javax.lang.model.util.Types
-dontwarn javax.tools.Diagnostic$Kind
-dontwarn javax.tools.JavaFileObject$Kind
-dontwarn javax.tools.JavaFileObject
-dontwarn javax.tools.SimpleJavaFileObject Custom Loader (Optional)
The SDK utilizes Lottie animations for the loading state. To override the default, place your custom Lottie file named loader_mix.json into the android/app/src/main/res/raw directory. Exact naming is required for proper integration.
Quick Start
1. Initialize SDK
To initialize the SDK, incorporate the following code into your android/app/src/main/yourpackage/MainActivity.kt file.
import android.content.Intent
import android.os.Bundle
import com.begenuin.genuin_sdk.GenuinSdkPlugin
import io.flutter.embedding.android.FlutterFragmentActivity
// Here we need to use FlutterFragmentActivity instead of FlutterActivity
class MainActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSdkPlugin.initSDK(this@MainActivity, "YOUR_API_KEY")
}
}2. Deep Linking Setup
To enable deep link routing, incorporate the following configuration into your android/app/src/main/AndroidManifest.xml file:
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="YOUR_WHITE-LABELLED_DOMAIN" android:scheme="https" />
</intent-filter>
</activity> To initialize the SDK, incorporate the following code into your android/app/src/main/yourpackage/MainActivity.kt file:
import android.content.Intent
import android.os.Bundle
import com.begenuin.genuin_sdk.GenuinSdkPlugin
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSdkPlugin.initSDK(this@MainActivity, "YOUR_API_KEY")
handleDeepLink(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleDeepLink(intent)
}
private fun handleDeepLink(intent: Intent?) {
intent?.data?.let {
GenuinSdkPlugin.handleDeepLink(this@MainActivity, intent)
}
}
} iOS Setup
iOS Configuration
Complete the following configuration steps and insert the provided code snippets into their respective files to integrate the Flutter SDK for iOS.
Step 1: Within ios/Podfile:
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
if target.name == 'Giphy'
`xcrun -sdk iphoneos bitcode_strip -r Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK -o Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK`
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end Quick Start Guide
1. SDK Initialization
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
//We are using lottie animation for our loader. You can put your custom lottie animation loader in your app's resources. update the "YOUR_LOTTIE_LOADER_NAME" with your loader name while initialize sdk.
GeneratedPluginRegistrant.register(with: self)
//UINavigationController is required for the redirection purpose in native component
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
} 2. Deep Linking Setup
To enable deep link routing, incorporate the following configuration into your AppDelegate.swift file:
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
GeneratedPluginRegistrant.register(with: self)
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
let result = GenuinSdkPlugin.flutterapplication(application, continue: userActivity, restorationHandler: restorationHandler)
if GenuinSdkPlugin.handleDeepLink(dlURL: userActivity.webpageURL, controller: window?.rootViewController) {
return true
}
return result
}
}3. Push Notifications Setup
To enable push notification routing, incorporate the following configuration into your AppDelegate.swift file:
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
UNUserNotificationCenter.current().delegate = self
GeneratedPluginRegistrant.register(with: self)
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("\(userInfo )")
completionHandler(.newData)
}
override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//removed banner to show in app notification
if #available(iOS 14.0, *) {
completionHandler([.banner, .list, .badge, .sound])
} else {
// Fallback on earlier versions
completionHandler([])
}
}
} Implementation in Flutter
1. Loading the Feed View
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: GenuinFeedView(),
),
);
} 2. Load Carousel Embed View
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: SizedBox(
height: 400, // here you can give height as per your need.
width: MediaQuery
.of(context)
.size
.width, // here you can give width as per your need.
child: const GenuinCarouselEmbedView(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
} You can configure the EmbedParams to meet your specific requirements by passing the following values:
- embedId (Required): The unique identifier for the embed content you wish to load
- uniqueId: An optional parameter used when displaying the same embedId across multiple screens or within the same view; ensures distinct instances are managed correctly
- ssoToken: An optional parameter used to facilitate automatic login; pass your SSO token to enable seamless user authentication within the SDK
- interactionDeepLink: An optional parameter that redirects all full-screen interactions to a specified URL; ensure the URL is valid to prevent redirection failure
- isDirectDeepLinkEnabled: An optional boolean (default: false) that redirects interactions to specific videos within a white-labelled application, overriding any provided interactionDeepLink
To utilize isDirectDeepLinkEnabled, your domain must be white-labelled, and deep link handling must be fully integrated within the destination application.
- isShowProfileEnabled: An optional boolean (default: false); when enabled for logged-in users, the profile picture is displayed in the full-screen view, providing access to account settings and logout options
3. Load Full Screen/Standard Wall Embed View
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: SizedBox(
height: MediaQuery
.of(context)
.size
.height, // here you can give height as per your need.
width: MediaQuery
.of(context)
.size
.width, // here you can give width as per your need.
child: const GenuinFeedEmbedView(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
} You can configure the EmbedParams to meet your specific requirements by passing the following values:
- embedId (Required): The unique identifier for the embed content you wish to load
- uniqueId: An optional parameter used when displaying the same embedId across multiple screens or within the same view; ensures distinct instances are managed correctly
- ssoToken: An optional parameter used to facilitate automatic login; pass your SSO token to enable seamless user authentication within the SDK
- interactionDeepLink: An optional parameter that redirects all full-screen interactions to a specified URL; ensure the URL is valid to prevent redirection failure
- isDirectDeepLinkEnabled: An optional boolean (default: false) that redirects interactions to specific videos within a white-labelled application, overriding any provided interactionDeepLink
To utilize isDirectDeepLinkEnabled, your domain must be white-labelled, and deep link handling must be fully integrated within the destination application.
- isShowProfileEnabled: An optional boolean (default: false); when enabled for logged-in users, the profile picture is displayed in the full-screen view, providing access to account settings and logout options
4. Push Notifications (Flutter)
Prerequisite
Create a Firebase project and integrate it into your application by following the setup guide at https://firebase.google.com/docs/flutter/setup.
Step 1. Firebase Configuration: Within lib/firebase_options.dart, initialize the Firebase options with the following details:
import 'package:firebase_core/firebase_core.dart';
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (Platform.isAndroid) {
return const FirebaseOptions(
apiKey: 'YOUR-ANDROID-API-KEY',
appId: 'YOUR-ANDROID-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}else{
return const FirebaseOptions(
apiKey: 'YOUR-IOS-API-KEY',
appId: 'YOUR-IOS-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}
}
} 2. Handling background/foreground notifications
For Android, you must provide a small notification icon using the "icon" key to handle foreground notifications correctly. This icon must be present in both your flutter and android directories.
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:genuin_sdk/genuin_sdk.dart';
import 'firebase_options.dart';
// This method will be called when app is in background and push received
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
final _genuinSdkPlugin = GenuinSdk();
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
name: 'YOUR_FIREBASE_PROJECT_NAME',
options: DefaultFirebaseOptions.currentPlatform,
);
final messaging = FirebaseMessaging.instance;
// Asking push notification permission
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// If permission is granted than get firebase token and register it with Genuin SDK
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
String? token = await messaging.getToken();
if (token != null) {
await _genuinSdkPlugin.registerFCMToken(token);
}
}
// Check for initial notification that opened the app
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
// Handle navigation or actions
final notificationData = {
'title': initialMessage.notification?.title,
'body': initialMessage.notification?.body,
'data': initialMessage.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
}
// This method will be called when app is in foreground and push received
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (kDebugMode) {
print('Handling a foreground message: ${message.messageId}');
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
'icon': 'mipmap/ic_notification'
// OR 'icon':'drawable/ic_notification'[if image put under drawable folder]
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleForegroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleForegroundNotifications(notificationData);
} else {
// Your notification handling
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//This method will be called when user clicked on notification[Push notification is received when app is in background/killed]
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
});
runApp(const MyApp());
} Step 5: Handle SSO Login explicitly in SDK
To facilitate Auto Login within the SDK, invoke the following method whenever a user authenticates in your application:
This method is not required if you have already implemented an Embed with SSO configuration.
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogin("YOUR_SSO_TOKEN"); Step 6: Handle SSO Logout explicitly in SDK
To terminate the authenticated session within the SDK, invoke the following method whenever a user logs out of your application:
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogout();Specs & Limitations
System Requirements
| Component | Requirement |
|---|---|
| Android | SDK 24+ |
| iOS | iOS 13+ |
| Framework | Flutter |
| Orientation | Portrait only |
| Internet | Mandatory |
Validation Rules
- API Key is mandatory for SDK initialization
- Embed ID must be valid and configured in BCC
- Deep linking requires a white-labelled domain
- SSO requires a valid token
System Behavior
- SDK initializes during app launch
- Deep links are automatically routed if configured
- Video playback lifecycle is managed internally
- Push notifications are handled via SDK hooks
Best Practices
- Initialize SDK early in app lifecycle
- Use unique IDs for multiple embeds
- Validate embed IDs and API keys before deployment
- Implement deep linking for seamless navigation
- Test push notifications across all app states