Flutter集成Genuin服务插件genuin_sdk的使用
Flutter集成Genuin服务插件genuin_sdk的使用
Genuin SDK包含品牌信息流、社区和群组等功能。
⬇️ 安装
在您的Flutter项目的pubspec.yaml
文件中添加genuin_sdk
依赖项:
dependencies:
genuin_sdk: <latest_version>
Android
Android配置
- 在
android/build.gradle
文件中:
allprojects {
repositories {
google()
mavenCentral()
// 添加jitpack
maven {
setUrl("https://jitpack.io")
}
}
}
- 在
android/app/build.gradle
文件中:
android {
defaultConfig {
minSdk = 24
}
}
- 在
android/app/src/main/AndroidManifest.xml
文件中:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- 添加 tools:replace="android:label" -->
<application android:label="genuin_sdk_example" android:icon="@mipmap/ic_launcher"
tools:replace="android:label">
<!-- 1. 如果想要处理深度链接,将启动模式改为singleTask
2. 移除 android:taskAffinity=""
3. 为了更好的SDK性能,使用 android:windowSoftInputMode="adjustPan"
-->
<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="adjustPan">
<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>
- 更改主题在
android/app/src/main/res/values/styles.xml
文件中:
我们的SDK使用Material组件,因此您需要使用Material主题,如以下示例所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 当OS的黑暗模式设置关闭时应用于Android窗口的主题 -->
<style name="LaunchTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
<!-- 显示启动屏幕。当Flutter引擎绘制第一帧时自动移除 -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- 当进程启动时应用于Android窗口的主题。
此主题确定Flutter UI初始化期间以及运行时窗口后面的颜色。
这个主题仅从Flutter的Android嵌入版本V2开始使用。 -->
<style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
- 创建
android/app/proguard-rules.pro
文件,并添加以下行:
# 添加项目特定的ProGuard规则
# 您可以使用build.gradle中的proguardFiles设置控制应用的配置文件集
#
# 更多详情,请访问
# http://developer.android.com/guide/developing/tools/proguard.html
# 取消注释以保留调试堆栈跟踪的行号信息
#-keepattributes SourceFile,LineNumberTable
-keep class com.bumptech.glide.**{*;}
-keep public class * {
public *;
protected *;
}
# Retrofit进行反射时需要Signature和EnclosingMethod属性
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit进行反射时需要RuntimeVisibleAnnotations和RuntimeVisibleParameterAnnotations属性
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# 保持服务方法参数以优化
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
# 忽略用于构建工具的注解
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# 忽略JSR 305注解,用于嵌入空值信息
-dontwarn javax.annotation.**
# 由NoClassDefFoundError try/catch保护,仅在类路径上使用
-dontwarn kotlin.Unit
# 仅由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
# 使用R8全模式时,它看不到通过代理创建的Retrofit接口的子类型,并用null替换所有潜在值。显式保留这些接口可以防止这种情况。
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
##---------------Begin: proguard configuration for Gson ----------
# Gson在工作时会存储类文件中的泛型类型信息。默认情况下,ProGuard会删除此类信息,因此在此处配置以保留所有信息。
-keepattributes Signature
# 对于使用Gson @Expose注解
-keepattributes *Annotation*
# Gson特定类
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# 应序列化/反序列化的应用程序类
-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
- 想要覆盖我们的默认加载器
我们使用Lottie动画作为加载器。您可以将自定义的Lottie动画加载器命名为loader_mix.json
并放在android/app/src/main/res/raw
文件夹中。确保您使用的是提供的名称。
快速开始
- 初始化SDK
import android.content.Intent
import android.os.Bundle
import com.begenuin.genuin_sdk.GenuinSdkPlugin
import io.flutter.embedding.android.FlutterFragmentActivity
// 这里我们需要使用FlutterFragmentActivity而不是FlutterActivity
class MainActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSdkPlugin.initSDK(this@MainActivity, "YOUR_API_KEY")
}
}
- 处理深度链接
在android/app/src/main/AndroidManifest.xml
文件中:
<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>
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
iOS配置
- 在
ios/Podfile
文件中:
# 取消注释此行以定义项目的全局平台
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
快速开始
- 初始化SDK
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")
// 我们使用Lottie动画作为加载器。您可以在应用资源中放置自定义Lottie动画加载器。初始化SDK时更新“YOUR_LOTTIE_LOADER_NAME”为您的加载器名称。
GeneratedPluginRegistrant.register(with: self)
// UINavigationController在原生组件中用于重定向目的
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = GenuinSdkPlugin.getGenuinNavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
- 处理深度链接
在AppDelegate.swift
文件中:
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 = GenuinSdkPlugin.getGenuinNavigationController(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
}
}
- 处理推送通知
在AppDelegate.swift
文件中:
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 = GenuinSdkPlugin.getGenuinNavigationController(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)")
// 移除横幅以显示应用内通知
if #available(iOS 14.0, *) {
completionHandler([.banner, .list, .badge, .sound])
} else {
// 在早期版本上回退
completionHandler([])
}
}
}
Flutter
- 加载轮播嵌入视图
import 'package:genuin_sdk/genuin_carousel_embed_view.dart';
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SizedBox(
height: 300, // 根据需要调整高度
width: MediaQuery.of(context).size.width, // 根据需要调整宽度
child: const Carousel(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
}
要暂停/恢复轮播视频
import 'package:genuin_sdk/genuin_sdk.dart';
setState(() {
final _genuinSdkPlugin = GenuinSdk();
// 添加您要暂停/恢复视频的轮播embedId/uniqueId。
final carouselConfig = {
'embedId': "YOUR_EMBED_ID",
'uniqueId': "UNIQUE_ID"
};
// 恢复视频播放
_genuinSdkPlugin.resumeCarousel(carouselConfig);
// 暂停视频播放
_genuinSdkPlugin.pauseCarousel(carouselConfig);
});
要根据需要配置嵌入参数,您可以传递以下值。
- embedId = 您要加载的嵌入ID。
- uniqueId = 这是一个可选参数。当我们在同一屏幕上显示相同的嵌入时,需要使用此唯一ID。对于同一嵌入ID在同一屏幕上多次显示,需要提供唯一ID。
- ssoToken = 这是一个可选参数。为了在应用中实现嵌入SSO,您应该传递“YOUR_SSO_TOKEN”。
- interactionDeepLink = 这是一个可选参数。您可以在此参数中传递一个深度链接URL。如果提供了深度链接URL,则全屏视图中的所有交互/点击将重定向到给定的深度链接URL。如果没有传递,则将按常规流程工作。如果不正确,则用户不会被重定向。
- isDirectDeepLinkEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真,则全屏视图中的所有交互/点击将重定向到与视频关联的白标应用中的特定视频,并且“interactionDeepLink”参数的值将被忽略。如果没有传递,则将按常规流程工作。
- 注意:要使用
isDirectDeepLinkEnabled
参数,您必须首先对您的域进行白标,并在您要重定向此视频的主应用中集成深度链接部分。 - isShowProfileEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真并且用户已登录,则全屏视图(右上角)将显示个人资料图片。单击个人资料图片,用户将看到帐户设置和登出选项。
- 加载标准墙嵌入视图
import 'package:genuin_sdk/genuin_standard_wall_view.dart';
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SizedBox(
height: MediaQuery.of(context).size.height, // 根据需要调整高度
width: MediaQuery.of(context).size.width, // 根据需要调整宽度
child: const StandardWall(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
}
要暂停/恢复标准墙视频
import 'package:genuin_sdk/genuin_sdk.dart';
setState(() {
final _genuinSdkPlugin = GenuinSdk();
// 添加您要暂停/恢复视频的标准墙embedId/uniqueId。
final standardWallConfig = {
'embedId': "YOUR_EMBED_ID",
'uniqueId': "UNIQUE_ID"
};
// 恢复视频播放
_genuinSdkPlugin.resumeStandWall(standardWallConfig);
// 暂停视频播放
_genuinSdkPlugin.pauseStandWall(standardWallConfig);
});
要根据需要配置嵌入参数,您可以传递以下值。
- embedId = 您要加载的嵌入ID。
- uniqueId = 这是一个可选参数。当我们在同一屏幕上显示相同的嵌入时,需要使用此唯一ID。对于同一嵌入ID在同一屏幕上多次显示,需要提供唯一ID。
- ssoToken = 这是一个可选参数。为了在应用中实现嵌入SSO,您应该传递“YOUR_SSO_TOKEN”。
- interactionDeepLink = 这是一个可选参数。您可以在此参数中传递一个深度链接URL。如果提供了深度链接URL,则全屏视图中的所有交互/点击将重定向到给定的深度链接URL。如果没有传递,则将按常规流程工作。如果不正确,则用户不会被重定向。
- isDirectDeepLinkEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真,则全屏视图中的所有交互/点击将重定向到与视频关联的白标应用中的特定视频,并且“interactionDeepLink”参数的值将被忽略。如果没有传递,则将按常规流程工作。
- 注意:要使用
isDirectDeepLinkEnabled
参数,您必须首先对您的域进行白标,并在您要重定向此视频的主应用中集成深度链接部分。 - isShowProfileEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真并且用户已登录,则全屏视图(右上角)将显示个人资料图片。单击个人资料图片,用户将看到帐户设置和登出选项。
- 加载全屏嵌入视图
import 'package:genuin_sdk/genuin_feed_embed_view.dart';
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SizedBox(
height: MediaQuery.of(context).size.height, // 根据需要调整高度
width: MediaQuery.of(context).size.width, // 根据需要调整宽度
child: const Feed(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
}
要暂停/恢复全屏视图中的视频
import 'package:genuin_sdk/genuin_sdk.dart';
setState(() {
final _genuinSdkPlugin = GenuinSdk();
// 添加您要暂停/恢复视频的全屏视图embedId/uniqueId。
final feedConfig = {
'embedId': "YOUR_EMBED_ID",
'uniqueId': "UNIQUE_ID"
};
// 恢复视频播放
_genuinSdkPlugin.resumeFeed(feedConfig);
// 暂停视频播放
_genuinSdkPlugin.pauseFeed(feedConfig);
});
要根据需要配置嵌入参数,您可以传递以下值。
- embedId = 您要加载的嵌入ID。
- uniqueId = 这是一个可选参数。当我们在同一屏幕上显示相同的嵌入时,需要使用此唯一ID。对于同一嵌入ID在同一屏幕上多次显示,需要提供唯一ID。
- ssoToken = 这是一个可选参数。为了在应用中实现嵌入SSO,您应该传递“YOUR_SSO_TOKEN”。
- interactionDeepLink = 这是一个可选参数。您可以在此参数中传递一个深度链接URL。如果提供了深度链接URL,则全屏视图中的所有交互/点击将重定向到给定的深度链接URL。如果没有传递,则将按常规流程工作。如果不正确,则用户不会被重定向。
- isDirectDeepLinkEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真,则全屏视图中的所有交互/点击将重定向到与视频关联的白标应用中的特定视频,并且“interactionDeepLink”参数的值将被忽略。如果没有传递,则将按常规流程工作。
- 注意:要使用
isDirectDeepLinkEnabled
参数,您必须首先对您的域进行白标,并在您要重定向此视频的主应用中集成深度链接部分。 - isShowProfileEnabled = 这是一个可选布尔参数,默认值为false。如果此参数为真并且用户已登录,则全屏视图(右上角)将显示个人资料图片。单击个人资料图片,用户将看到帐户设置和登出选项。
- 加载HomeFeed视图(Android特定)
import 'package:genuin_sdk/genuin_feed_view.dart';
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: HomeFeed(),
),
);
}
- 处理推送通知
前提条件:
创建Firebase项目并将其集成到您的应用中,遵循Firebase文档。
步骤:
- 在lib文件夹中创建
firebase_options.dart
文件,并添加以下详细信息:
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',
);
}
}
}
- 处理后台/前台通知
注意:对于Android,您需要提供小的通知图标作为“icon”键以处理前台通知。该图标需要同时存在于您的Flutter项目和Android文件夹中。
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';
// 当应用在后台收到推送消息时调用此方法
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;
// 请求推送通知权限
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// 如果权限被授予,则获取Firebase令牌并将其注册到Genuin SDK
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
String? token = await messaging.getToken();
if (token != null) {
await _genuinSdkPlugin.registerFCMToken(token);
}
}
// 检查打开应用的初始通知
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
// 处理导航或操作
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 {
// 您的通知处理
}
}
// 当应用在前台收到推送消息时调用此方法
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'
// 或者 'icon':'drawable/ic_notification'[如果图像放在drawable文件夹下]
};
var willHandleNotification = await _genuinSdkPlugin.willHandleForegroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleForegroundNotifications(notificationData);
} else {
// 您的通知处理
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
// 当用户点击通知时调用此方法[当应用在后台/已关闭时收到推送通知]
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 {
// 您的通知处理
}
});
runApp(const MyApp());
}
- 在SDK中显式处理SSO登录
要自动登录到SDK,您需要在用户登录到您的应用时调用以下方法。
注意:如果您已经实现了嵌入SSO,则不需要调用以下方法。
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogin("YOUR_SSO_TOKEN");
- 在SDK中处理SSO注销
每当用户从您的应用中注销时,请调用以下方法。
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogout();
示例代码
import 'package:flutter/material.dart';
import 'package:genuin_sdk/genuin_carousel_embed_view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
[@override](/user/override)
void initState() {
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('插件示例应用'),
),
body: Column(
children: [
SizedBox(
height: 300,
width: MediaQuery.of(context).size.width,
child: const Carousel(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
)
],
),
),
);
}
}
更多关于Flutter集成Genuin服务插件genuin_sdk的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter集成Genuin服务插件genuin_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
要在Flutter项目中集成genuin_sdk
插件以使用Genuin服务,你可以按照以下步骤进行操作:
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加genuin_sdk
插件的依赖:
dependencies:
flutter:
sdk: flutter
genuin_sdk: ^1.0.0 # 请使用最新版本
然后运行flutter pub get
来获取依赖。
2. 初始化Genuin SDK
在你的Flutter应用中,你需要初始化Genuin SDK。通常,你可以在main.dart
中的main
函数中或者在应用的启动逻辑中进行初始化。
import 'package:genuin_sdk/genuin_sdk.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化Genuin SDK
await GenuinSdk.initialize(
apiKey: 'YOUR_API_KEY', // 替换为你的API Key
environment: GenuinEnvironment.production, // 或 GenuinEnvironment.sandbox
);
runApp(MyApp());
}
3. 使用Genuin SDK
初始化后,你可以在应用的不同部分使用Genuin SDK提供的功能。以下是一些常见的用法示例:
3.1 验证设备
你可以使用Genuin SDK来验证设备的真实性:
import 'package:genuin_sdk/genuin_sdk.dart';
Future<void> verifyDevice() async {
try {
bool isGenuine = await GenuinSdk.verifyDevice();
if (isGenuine) {
print('设备是正版的');
} else {
print('设备可能是盗版的');
}
} catch (e) {
print('验证失败: $e');
}
}
3.2 获取设备信息
你可以获取设备的详细信息:
import 'package:genuin_sdk/genuin_sdk.dart';
Future<void> getDeviceInfo() async {
try {
Map<String, dynamic> deviceInfo = await GenuinSdk.getDeviceInfo();
print('设备信息: $deviceInfo');
} catch (e) {
print('获取设备信息失败: $e');
}
}
4. 处理回调
Genuin SDK可能会在某些情况下触发回调,例如设备状态变化。你可以注册回调来处理这些事件:
import 'package:genuin_sdk/genuin_sdk.dart';
void setupCallbacks() {
GenuinSdk.onDeviceStatusChanged((status) {
print('设备状态变化: $status');
});
}
5. 配置Android和iOS
根据Genuin SDK的要求,你可能需要在Android和iOS项目中进行一些额外的配置。
Android
在android/app/build.gradle
文件中,确保你启用了multidex
:
android {
defaultConfig {
multiDexEnabled true
}
}
iOS
在ios/Runner/Info.plist
文件中,添加必要的权限和配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>