diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5e398b..3431240 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## Next
- chore: change host to new address ([#106](https://github.com/PostHog/posthog-flutter/pull/106))
+- chore: allow manual initialization of the SDK ([#117](https://github.com/PostHog/posthog-flutter/pull/117))
## 4.5.0
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ca99bbd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+.PHONY: formatKotlin formatSwift formatDart
+
+# brew install ktlint
+# TODO: add ktlint steps in CI
+formatKotlin:
+ ktlint --format
+
+# brew install swiftlint
+# TODO: add swiftlint steps in CI
+formatSwift:
+ swiftformat ios/Classes --swiftversion 5.3
+ swiftlint ios/Classes --fix
+
+formatDart:
+ dart format .
+ dart analyze .
diff --git a/README.md b/README.md
index c4e71c4..434951c 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ To use this plugin, add `posthog_flutter` as a [dependency in your pubspec.yaml
| Method | Android | iOS/macOS | Web |
| ------------------------- | ------- | --------- | --- |
+| `setup` | X | X | |
| `identify` | X | X | X |
| `capture` | X | X | X |
| `screen` | X | X | X |
@@ -29,6 +30,7 @@ To use this plugin, add `posthog_flutter` as a [dependency in your pubspec.yaml
| `getFeatureFlag` | X | X | X |
| `getFeatureFlagPayload` | X | X | X |
| `group` | X | X | X |
+| `close` | X | X | |
### Example
@@ -80,9 +82,9 @@ Remember that the application lifecycle events won't have any special context se
### Android
-#### AndroidManifest.xml
+Automatically:
-```xml
+```xml file=AndroidManifest.xml
@@ -97,11 +99,40 @@ Remember that the application lifecycle events won't have any special context se
```
+Or manually, disable the auto init:
+
+```xml file=AndroidManifest.xml
+
+
+
+ [...]
+
+
+
+
+```
+
+And setup the SDK manually:
+
+```dart
+Future main() async {
+ // init WidgetsFlutterBinding if not yet
+ WidgetsFlutterBinding.ensureInitialized();
+ final config = PostHogConfig('YOUR_API_KEY_GOES_HERE');
+ config.debug = true;
+ config.captureApplicationLifecycleEvents = true;
+ // or EU Host: 'https://eu.i.posthog.com'
+ config.host = 'https://us.i.posthog.com';
+ await Posthog().setup(config);
+ runApp(MyApp());
+}
+```
+
### iOS/macOS
-#### Info.plist
+Automatically:
-```xml
+```xml file=Info.plist
@@ -121,9 +152,40 @@ Remember that the application lifecycle events won't have any special context se
```
+Or manually, disable the auto init:
+
+```xml file=Info.plist
+
+
+
+
+ [...]
+ com.posthog.posthog.AUTO_INIT
+
+ [...]
+
+
+```
+
+And setup the SDK manually:
+
+```dart
+Future main() async {
+ // init WidgetsFlutterBinding if not yet
+ WidgetsFlutterBinding.ensureInitialized();
+ final config = PostHogConfig('YOUR_API_KEY_GOES_HERE');
+ config.debug = true;
+ config.captureApplicationLifecycleEvents = true;
+ // or EU Host: 'https://eu.i.posthog.com'
+ config.host = 'https://us.i.posthog.com';
+ await Posthog().setup(config);
+ runApp(MyApp());
+}
+```
+
### Web
-```html
+```html file=index.html
diff --git a/android/src/main/kotlin/com/posthog/posthog_flutter/PosthogFlutterPlugin.kt b/android/src/main/kotlin/com/posthog/posthog_flutter/PosthogFlutterPlugin.kt
index a921be4..fb97fbf 100644
--- a/android/src/main/kotlin/com/posthog/posthog_flutter/PosthogFlutterPlugin.kt
+++ b/android/src/main/kotlin/com/posthog/posthog_flutter/PosthogFlutterPlugin.kt
@@ -1,8 +1,12 @@
package com.posthog.posthog_flutter
import android.content.Context
+import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
import android.util.Log
+import com.posthog.PersonProfiles
import com.posthog.PostHog
import com.posthog.PostHogConfig
import com.posthog.android.PostHogAndroid
@@ -14,27 +18,54 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** PosthogFlutterPlugin */
-class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
- /// The MethodChannel that will the communication between Flutter and native Android
- ///
- /// This local reference serves to register the plugin with the Flutter Engine and unregister it
- /// when the Flutter Engine is detached from the Activity
+class PosthogFlutterPlugin :
+ FlutterPlugin,
+ MethodCallHandler {
+ // / The MethodChannel that will be the communication between Flutter and native Android
+ // /
+ // / This local reference serves to register the plugin with the Flutter Engine and unregister it
+ // / when the Flutter Engine is detached from the Activity
private lateinit var channel: MethodChannel
+ private lateinit var applicationContext: Context
+
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "posthog_flutter")
- initPlugin(flutterPluginBinding.applicationContext)
+ this.applicationContext = flutterPluginBinding.applicationContext
+ initPlugin()
channel.setMethodCallHandler(this)
}
- private fun initPlugin(applicationContext: Context) {
+ // TODO: expose on the android SDK instead
+ @Throws(PackageManager.NameNotFoundException::class)
+ private fun getApplicationInfo(context: Context): ApplicationInfo =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ context
+ .packageManager
+ .getApplicationInfo(
+ context.packageName,
+ PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
+ )
+ } else {
+ context
+ .packageManager
+ .getApplicationInfo(context.packageName, PackageManager.GET_META_DATA)
+ }
+
+ private fun initPlugin() {
try {
- // TODO: replace deprecated method API 33
- val ai = applicationContext.packageManager.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
- val bundle = ai.metaData
- val apiKey = bundle.getString("com.posthog.posthog.API_KEY", null)
+ val ai = getApplicationInfo(applicationContext)
+ val bundle = ai.metaData ?: Bundle()
+ val autoInit = bundle.getBoolean("com.posthog.posthog.AUTO_INIT", true)
+
+ if (!autoInit) {
+ Log.i("PostHog", "com.posthog.posthog.AUTO_INIT is disabled!")
+ return
+ }
+
+ val apiKey = bundle.getString("com.posthog.posthog.API_KEY")
if (apiKey.isNullOrEmpty()) {
Log.e("PostHog", "com.posthog.posthog.API_KEY is missing!")
@@ -42,29 +73,29 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
val host = bundle.getString("com.posthog.posthog.POSTHOG_HOST", PostHogConfig.DEFAULT_HOST)
- val trackApplicationLifecycleEvents = bundle.getBoolean("com.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS", false)
- val enableDebug = bundle.getBoolean("com.posthog.posthog.DEBUG", false)
+ val captureApplicationLifecycleEvents = bundle.getBoolean("com.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS", false)
+ val debug = bundle.getBoolean("com.posthog.posthog.DEBUG", false)
- // Init PostHog
- val config = PostHogAndroidConfig(apiKey, host).apply {
- captureScreenViews = false
- captureDeepLinks = false
- captureApplicationLifecycleEvents = trackApplicationLifecycleEvents
- debug = enableDebug
- sdkName = "posthog-flutter"
- sdkVersion = postHogVersion
- }
- PostHogAndroid.setup(applicationContext, config)
+ val posthogConfig = mutableMapOf()
+ posthogConfig["apiKey"] = apiKey
+ posthogConfig["host"] = host
+ posthogConfig["captureApplicationLifecycleEvents"] = captureApplicationLifecycleEvents
+ posthogConfig["debug"] = debug
+ setupPostHog(posthogConfig)
} catch (e: Throwable) {
- e.localizedMessage?.let { Log.e("PostHog", "initPlugin error: $it") }
+ Log.e("PostHog", "initPlugin error: $e")
}
}
- override fun onMethodCall(call: MethodCall, result: Result) {
-
+ override fun onMethodCall(
+ call: MethodCall,
+ result: Result,
+ ) {
when (call.method) {
-
+ "setup" -> {
+ setup(call, result)
+ }
"identify" -> {
identify(call, result)
}
@@ -129,18 +160,95 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
"flush" -> {
flush(result)
}
+ "close" -> {
+ close(result)
+ }
else -> {
result.notImplemented()
}
}
+ }
+
+ private fun setup(
+ call: MethodCall,
+ result: Result,
+ ) {
+ try {
+ val args = call.arguments() as Map? ?: mapOf()
+ if (args.isEmpty()) {
+ result.error("PosthogFlutterException", "Arguments is null or empty", null)
+ return
+ }
+
+ setupPostHog(args)
+
+ result.success(null)
+ } catch (e: Throwable) {
+ result.error("PosthogFlutterException", e.localizedMessage, null)
+ }
+ }
+
+ private fun setupPostHog(posthogConfig: Map) {
+ val apiKey = posthogConfig["apiKey"] as String?
+ if (apiKey.isNullOrEmpty()) {
+ Log.e("PostHog", "apiKey is missing!")
+ return
+ }
+
+ val host = posthogConfig["host"] as String? ?: PostHogConfig.DEFAULT_HOST
+ val config =
+ PostHogAndroidConfig(apiKey, host).apply {
+ captureScreenViews = false
+ captureDeepLinks = false
+ posthogConfig.getIfNotNull("captureApplicationLifecycleEvents") {
+ captureApplicationLifecycleEvents = it
+ }
+ posthogConfig.getIfNotNull("debug") {
+ debug = it
+ }
+ posthogConfig.getIfNotNull("flushAt") {
+ flushAt = it
+ }
+ posthogConfig.getIfNotNull("maxQueueSize") {
+ maxQueueSize = it
+ }
+ posthogConfig.getIfNotNull("maxBatchSize") {
+ maxBatchSize = it
+ }
+ posthogConfig.getIfNotNull("flushInterval") {
+ flushIntervalSeconds = it
+ }
+ posthogConfig.getIfNotNull("sendFeatureFlagEvents") {
+ sendFeatureFlagEvent = it
+ }
+ posthogConfig.getIfNotNull("preloadFeatureFlags") {
+ preloadFeatureFlags = it
+ }
+ posthogConfig.getIfNotNull("optOut") {
+ optOut = it
+ }
+ posthogConfig.getIfNotNull("personProfiles") {
+ when (it) {
+ "never" -> personProfiles = PersonProfiles.NEVER
+ "always" -> personProfiles = PersonProfiles.ALWAYS
+ "identifiedOnly" -> personProfiles = PersonProfiles.IDENTIFIED_ONLY
+ }
+ }
+ sdkName = "posthog-flutter"
+ sdkVersion = postHogVersion
+ }
+ PostHogAndroid.setup(applicationContext, config)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
- private fun getFeatureFlag(call: MethodCall, result: Result) {
+ private fun getFeatureFlag(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val featureFlagKey: String = call.argument("key")!!
val flag = PostHog.getFeatureFlag(featureFlagKey)
@@ -150,7 +258,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun getFeatureFlagPayload(call: MethodCall, result: Result) {
+ private fun getFeatureFlagPayload(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val featureFlagKey: String = call.argument("key")!!
val flag = PostHog.getFeatureFlagPayload(featureFlagKey)
@@ -160,7 +271,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun identify(call: MethodCall, result: Result) {
+ private fun identify(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val userId: String = call.argument("userId")!!
val userProperties: Map? = call.argument("userProperties")
@@ -172,7 +286,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun capture(call: MethodCall, result: Result) {
+ private fun capture(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val eventName: String = call.argument("eventName")!!
val properties: Map? = call.argument("properties")
@@ -183,7 +300,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun screen(call: MethodCall, result: Result) {
+ private fun screen(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val screenName: String = call.argument("screenName")!!
val properties: Map? = call.argument("properties")
@@ -194,7 +314,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun alias(call: MethodCall, result: Result) {
+ private fun alias(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val alias: String = call.argument("alias")!!
PostHog.alias(alias)
@@ -231,7 +354,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun debug(call: MethodCall, result: Result) {
+ private fun debug(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val debug: Boolean = call.argument("debug")!!
PostHog.debug(debug)
@@ -250,7 +376,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun isFeatureEnabled(call: MethodCall, result: Result) {
+ private fun isFeatureEnabled(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val key: String = call.argument("key")!!
val isEnabled = PostHog.isFeatureEnabled(key)
@@ -269,7 +398,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun group(call: MethodCall, result: Result) {
+ private fun group(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val groupType: String = call.argument("groupType")!!
val groupKey: String = call.argument("groupKey")!!
@@ -281,7 +413,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun register(call: MethodCall, result: Result) {
+ private fun register(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val key: String = call.argument("key")!!
val value: Any = call.argument("value")!!
@@ -292,7 +427,10 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
}
}
- private fun unregister(call: MethodCall, result: Result) {
+ private fun unregister(
+ call: MethodCall,
+ result: Result,
+ ) {
try {
val key: String = call.argument("key")!!
PostHog.unregister(key)
@@ -310,4 +448,24 @@ class PosthogFlutterPlugin : FlutterPlugin, MethodCallHandler {
result.error("PosthogFlutterException", e.localizedMessage, null)
}
}
+
+ private fun close(result: Result) {
+ try {
+ PostHog.close()
+ result.success(null)
+ } catch (e: Throwable) {
+ result.error("PosthogFlutterException", e.localizedMessage, null)
+ }
+ }
+
+ // Call the `completion` closure if cast to map value with `key` and type `T` is successful.
+ @Suppress("UNCHECKED_CAST")
+ private fun Map.getIfNotNull(
+ key: String,
+ callback: (T) -> Unit,
+ ) {
+ (get(key) as? T)?.let {
+ callback(it)
+ }
+ }
}
diff --git a/android/src/test/kotlin/com/posthog/posthog_flutter/PosthogFlutterPluginTest.kt b/android/src/test/kotlin/com/posthog/posthog_flutter/PosthogFlutterPluginTest.kt
index b9a5d12..8d8da6a 100644
--- a/android/src/test/kotlin/com/posthog/posthog_flutter/PosthogFlutterPluginTest.kt
+++ b/android/src/test/kotlin/com/posthog/posthog_flutter/PosthogFlutterPluginTest.kt
@@ -2,8 +2,8 @@ package com.posthog.posthog_flutter
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
-import kotlin.test.Test
import org.mockito.Mockito
+import kotlin.test.Test
/*
* This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation.
@@ -14,12 +14,11 @@ import org.mockito.Mockito
*/
internal class PosthogFlutterPluginTest {
-
@Test
fun onMethodCall_identify_returnsExpectedValue() {
val plugin = PosthogFlutterPlugin()
- var arguments = mapOf("userId" to "abc");
+ var arguments = mapOf("userId" to "abc")
val call = MethodCall("identify", arguments)
val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
@@ -32,7 +31,7 @@ internal class PosthogFlutterPluginTest {
fun onMethodCall_alias_returnsExpectedValue() {
val plugin = PosthogFlutterPlugin()
- var arguments = mapOf("alias" to "abc");
+ var arguments = mapOf("alias" to "abc")
val call = MethodCall("alias", arguments)
val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 649438f..bb059f0 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -36,7 +36,7 @@
special context set for you by the time it is initialized. -->
+ android:value="phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" />
@@ -46,5 +46,7 @@
+
diff --git a/example/android/app/src/main/kotlin/com/example/posthog_flutter_example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/posthog_flutter_example/MainActivity.kt
index efdc6a1..1529f5a 100644
--- a/example/android/app/src/main/kotlin/com/example/posthog_flutter_example/MainActivity.kt
+++ b/example/android/app/src/main/kotlin/com/example/posthog_flutter_example/MainActivity.kt
@@ -2,5 +2,4 @@ package com.example.posthog_flutter_example
import io.flutter.embedding.android.FlutterActivity
-class MainActivity: FlutterActivity() {
-}
+class MainActivity : FlutterActivity()
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
index 97940ec..99dd680 100644
--- a/example/ios/Runner/Info.plist
+++ b/example/ios/Runner/Info.plist
@@ -44,7 +44,7 @@
com.posthog.posthog.POSTHOG_HOST
https://us.i.posthog.com
com.posthog.posthog.API_KEY
- _6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI
+ phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D
com.posthog.posthog.CAPTURE_APPLICATION_LIFECYCLE_EVENTS
com.posthog.posthog.DEBUG
@@ -53,5 +53,7 @@
UIApplicationSupportsIndirectInputEvents
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 40e1795..e525d84 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -2,7 +2,16 @@ import 'package:flutter/material.dart';
import 'package:posthog_flutter/posthog_flutter.dart';
-void main() {
+Future main() async {
+ // // init WidgetsFlutterBinding if not yet
+ // WidgetsFlutterBinding.ensureInitialized();
+ // final config =
+ // PostHogConfig('phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D');
+ // config.debug = true;
+ // config.captureApplicationLifecycleEvents = true;
+ // config.host = 'https://us.i.posthog.com';
+ // await Posthog().setup(config);
+
runApp(const MyApp());
}
diff --git a/example/macos/Runner/Info.plist b/example/macos/Runner/Info.plist
index dc2d6f0..55201d4 100644
--- a/example/macos/Runner/Info.plist
+++ b/example/macos/Runner/Info.plist
@@ -32,7 +32,7 @@
com.posthog.posthog.POSTHOG_HOST
https://us.i.posthog.com
com.posthog.posthog.API_KEY
- _6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI
+ phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D
com.posthog.posthog.CAPTURE_APPLICATION_LIFECYCLE_EVENTS
com.posthog.posthog.DEBUG
diff --git a/ios/Classes/PostHogFlutterVersion.swift b/ios/Classes/PostHogFlutterVersion.swift
index 5dcdd41..dbab251 100644
--- a/ios/Classes/PostHogFlutterVersion.swift
+++ b/ios/Classes/PostHogFlutterVersion.swift
@@ -8,4 +8,4 @@
import Foundation
// This property is internal only
-internal let postHogFlutterVersion = "4.5.0"
+let postHogFlutterVersion = "4.5.0"
diff --git a/ios/Classes/PosthogFlutterPlugin.swift b/ios/Classes/PosthogFlutterPlugin.swift
index 6fbfdb1..2f88607 100644
--- a/ios/Classes/PosthogFlutterPlugin.swift
+++ b/ios/Classes/PosthogFlutterPlugin.swift
@@ -1,55 +1,123 @@
import PostHog
#if os(iOS)
-import Flutter
-import UIKit
+ import Flutter
+ import UIKit
#elseif os(macOS)
-import FlutterMacOS
-import AppKit
+ import AppKit
+ import FlutterMacOS
#endif
public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
-#if os(iOS)
- let channel = FlutterMethodChannel(name: "posthog_flutter", binaryMessenger: registrar.messenger())
-#elseif os(macOS)
- let channel = FlutterMethodChannel(name: "posthog_flutter", binaryMessenger: registrar.messenger)
-#endif
+ #if os(iOS)
+ let channel = FlutterMethodChannel(name: "posthog_flutter", binaryMessenger: registrar.messenger())
+ #elseif os(macOS)
+ let channel = FlutterMethodChannel(name: "posthog_flutter", binaryMessenger: registrar.messenger)
+ #endif
let instance = PosthogFlutterPlugin()
initPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public static func initPlugin() {
- // Initialise PostHog
+ let autoInit = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.AUTO_INIT") as? Bool ?? true
+ if !autoInit {
+ print("[PostHog] com.posthog.posthog.AUTO_INIT is disabled!")
+ return
+ }
+
let apiKey = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.API_KEY") as? String ?? ""
+ let host = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.POSTHOG_HOST") as? String ?? PostHogConfig.defaultHost
+ let captureApplicationLifecycleEvents = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.CAPTURE_APPLICATION_LIFECYCLE_EVENTS") as? Bool ?? false
+ let debug = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.DEBUG") as? Bool ?? false
+
+ setupPostHog([
+ "apiKey": apiKey,
+ "host": host,
+ "captureApplicationLifecycleEvents": captureApplicationLifecycleEvents,
+ "debug": debug
+ ])
+ }
+
+ private static func setupPostHog(_ posthogConfig: [String: Any]) {
+ let apiKey = posthogConfig["apiKey"] as? String ?? ""
if apiKey.isEmpty {
- print("[PostHog] com.posthog.posthog.API_KEY is missing!")
+ print("[PostHog] apiKey is missing!")
return
}
- let host = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.POSTHOG_HOST") as? String ?? PostHogConfig.defaultHost
- let postHogCaptureLifecyleEvents = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.CAPTURE_APPLICATION_LIFECYCLE_EVENTS") as? Bool ?? false
- let postHogDebug = Bundle.main.object(forInfoDictionaryKey: "com.posthog.posthog.DEBUG") as? Bool ?? false
+ let host = posthogConfig["host"] as? String ?? PostHogConfig.defaultHost
let config = PostHogConfig(
apiKey: apiKey,
host: host
)
- config.captureApplicationLifecycleEvents = postHogCaptureLifecyleEvents
- config.debug = postHogDebug
config.captureScreenViews = false
-
+
+ if let captureApplicationLifecycleEvents = posthogConfig["captureApplicationLifecycleEvents"] as? Bool {
+ config.captureApplicationLifecycleEvents = captureApplicationLifecycleEvents
+ }
+ if let debug = posthogConfig["debug"] as? Bool {
+ config.debug = debug
+ }
+ if let flushAt = posthogConfig["flushAt"] as? Int {
+ config.flushAt = flushAt
+ }
+ if let maxQueueSize = posthogConfig["maxQueueSize"] as? Int {
+ config.maxQueueSize = maxQueueSize
+ }
+ if let maxBatchSize = posthogConfig["maxBatchSize"] as? Int {
+ config.maxBatchSize = maxBatchSize
+ }
+ if let flushInterval = posthogConfig["flushInterval"] as? Int {
+ config.flushIntervalSeconds = Double(flushInterval)
+ }
+ if let sendFeatureFlagEvents = posthogConfig["sendFeatureFlagEvents"] as? Bool {
+ config.sendFeatureFlagEvent = sendFeatureFlagEvents
+ }
+ if let preloadFeatureFlags = posthogConfig["preloadFeatureFlags"] as? Bool {
+ config.preloadFeatureFlags = preloadFeatureFlags
+ }
+ if let optOut = posthogConfig["optOut"] as? Bool {
+ config.optOut = optOut
+ }
+ if let personProfiles = posthogConfig["personProfiles"] as? String {
+ switch personProfiles {
+ case "never":
+ config.personProfiles = .never
+ case "always":
+ config.personProfiles = .always
+ case "identifiedOnly":
+ config.personProfiles = .identifiedOnly
+ default:
+ break
+ }
+ }
+ if let dataMode = posthogConfig["dataMode"] as? String {
+ switch dataMode {
+ case "wifi":
+ config.dataMode = .wifi
+ case "cellular":
+ config.dataMode = .cellular
+ case "any":
+ config.dataMode = .any
+ default:
+ break
+ }
+ }
+
// Update SDK name and version
- postHogSdkName = "posthog-flutter"
- postHogVersion = postHogFlutterVersion
-
+ postHogSdkName = "posthog-flutter"
+ postHogVersion = postHogFlutterVersion
+
PostHogSDK.shared.setup(config)
- //
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
+ case "setup":
+ setup(call, result: result)
case "getFeatureFlag":
getFeatureFlag(call, result: result)
case "isFeatureEnabled":
@@ -84,18 +152,31 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
unregister(call, result: result)
case "flush":
flush(result)
+ case "close":
+ close(result)
default:
result(FlutterMethodNotImplemented)
}
}
+ private func setup(
+ _ call: FlutterMethodCall,
+ result: @escaping FlutterResult
+ ) {
+ if let args = call.arguments as? [String: Any] {
+ PosthogFlutterPlugin.setupPostHog(args)
+ result(nil)
+ } else {
+ _badArgumentError(result)
+ }
+ }
+
private func getFeatureFlag(
_ call: FlutterMethodCall,
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let featureFlagKey = args["key"] as? String
- {
+ let featureFlagKey = args["key"] as? String {
let value = PostHogSDK.shared.getFeatureFlag(featureFlagKey)
result(value)
} else {
@@ -108,8 +189,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let featureFlagKey = args["key"] as? String
- {
+ let featureFlagKey = args["key"] as? String {
let value = PostHogSDK.shared.isFeatureEnabled(featureFlagKey)
result(value)
} else {
@@ -122,8 +202,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let featureFlagKey = args["key"] as? String
- {
+ let featureFlagKey = args["key"] as? String {
let value = PostHogSDK.shared.getFeatureFlagPayload(featureFlagKey)
result(value)
} else {
@@ -136,8 +215,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let userId = args["userId"] as? String
- {
+ let userId = args["userId"] as? String {
let userProperties = args["userProperties"] as? [String: Any]
let userPropertiesSetOnce = args["userPropertiesSetOnce"] as? [String: Any]
@@ -157,8 +235,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let eventName = args["eventName"] as? String
- {
+ let eventName = args["eventName"] as? String {
let properties = args["properties"] as? [String: Any]
PostHogSDK.shared.capture(
eventName,
@@ -175,8 +252,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let screenName = args["screenName"] as? String
- {
+ let screenName = args["screenName"] as? String {
let properties = args["properties"] as? [String: Any]
PostHogSDK.shared.screen(
screenName,
@@ -193,8 +269,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let alias = args["alias"] as? String
- {
+ let alias = args["alias"] as? String {
PostHogSDK.shared.alias(alias)
result(nil)
} else {
@@ -227,8 +302,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let debug = args["debug"] as? Bool
- {
+ let debug = args["debug"] as? Bool {
PostHogSDK.shared.debug(debug)
result(nil)
} else {
@@ -248,8 +322,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
) {
if let args = call.arguments as? [String: Any],
let groupType = args["groupType"] as? String,
- let groupKey = args["groupKey"] as? String
- {
+ let groupKey = args["groupKey"] as? String {
let groupProperties = args["groupProperties"] as? [String: Any]
PostHogSDK.shared.group(type: groupType, key: groupKey, groupProperties: groupProperties)
result(nil)
@@ -264,8 +337,7 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
) {
if let args = call.arguments as? [String: Any],
let key = args["key"] as? String,
- let value = args["value"]
- {
+ let value = args["value"] {
PostHogSDK.shared.register([key: value])
result(nil)
} else {
@@ -278,20 +350,24 @@ public class PosthogFlutterPlugin: NSObject, FlutterPlugin {
result: @escaping FlutterResult
) {
if let args = call.arguments as? [String: Any],
- let key = args["key"] as? String
- {
+ let key = args["key"] as? String {
PostHogSDK.shared.unregister(key)
result(nil)
} else {
_badArgumentError(result)
}
}
-
+
private func flush(_ result: @escaping FlutterResult) {
PostHogSDK.shared.flush()
result(nil)
}
+ private func close(_ result: @escaping FlutterResult) {
+ PostHogSDK.shared.close()
+ result(nil)
+ }
+
// Return bad Arguments error
private func _badArgumentError(_ result: @escaping FlutterResult) {
result(FlutterError(
diff --git a/lib/posthog_flutter.dart b/lib/posthog_flutter.dart
index 6250534..1e95495 100644
--- a/lib/posthog_flutter.dart
+++ b/lib/posthog_flutter.dart
@@ -1,4 +1,5 @@
library posthog_flutter;
export 'src/posthog.dart';
+export 'src/posthog_config.dart';
export 'src/posthog_observer.dart';
diff --git a/lib/posthog_flutter_web.dart b/lib/posthog_flutter_web.dart
index 93c75dc..83cccbe 100644
--- a/lib/posthog_flutter_web.dart
+++ b/lib/posthog_flutter_web.dart
@@ -24,7 +24,6 @@ class PosthogFlutterWeb extends PosthogFlutterPlatformInterface {
channel.setMethodCallHandler(instance.handleMethodCall);
}
- Future handleMethodCall(MethodCall call) async {
- return handleWebMethodCall(call, context);
- }
+ Future handleMethodCall(MethodCall call) =>
+ handleWebMethodCall(call, context);
}
diff --git a/lib/src/posthog.dart b/lib/src/posthog.dart
index d955fc3..88b34fc 100644
--- a/lib/src/posthog.dart
+++ b/lib/src/posthog.dart
@@ -1,3 +1,4 @@
+import 'posthog_config.dart';
import 'posthog_flutter_platform_interface.dart';
class Posthog {
@@ -12,16 +13,21 @@ class Posthog {
String? _currentScreen;
+ /// Android and iOS only
+ /// Only used for the manual setup
+ /// Requires disabling the automatic init on Android and iOS:
+ /// com.posthog.posthog.AUTO_INIT: false
+ Future setup(PostHogConfig config) => _posthog.setup(config);
+
Future identify({
required String userId,
Map? userProperties,
Map? userPropertiesSetOnce,
- }) {
- return _posthog.identify(
- userId: userId,
- userProperties: userProperties,
- userPropertiesSetOnce: userPropertiesSetOnce);
- }
+ }) =>
+ _posthog.identify(
+ userId: userId,
+ userProperties: userProperties,
+ userPropertiesSetOnce: userPropertiesSetOnce);
Future capture({
required String eventName,
@@ -44,82 +50,58 @@ class Posthog {
Future screen({
required String screenName,
Map? properties,
- }) {
- _currentScreen = screenName;
-
- return _posthog.screen(
- screenName: screenName,
- properties: properties,
- );
- }
+ }) =>
+ _posthog.screen(
+ screenName: screenName,
+ properties: properties,
+ );
Future alias({
required String alias,
- }) {
- return _posthog.alias(
- alias: alias,
- );
- }
+ }) =>
+ _posthog.alias(
+ alias: alias,
+ );
- Future getDistinctId() {
- return _posthog.getDistinctId();
- }
+ Future getDistinctId() => _posthog.getDistinctId();
- Future reset() {
- return _posthog.reset();
- }
+ Future reset() => _posthog.reset();
- Future disable() {
- return _posthog.disable();
- }
+ Future disable() => _posthog.disable();
- Future enable() {
- return _posthog.enable();
- }
+ Future enable() => _posthog.enable();
- Future debug(bool enabled) {
- return _posthog.debug(enabled);
- }
+ Future debug(bool enabled) => _posthog.debug(enabled);
- Future register(String key, Object value) {
- return _posthog.register(key, value);
- }
+ Future register(String key, Object value) =>
+ _posthog.register(key, value);
- Future unregister(String key) {
- return _posthog.unregister(key);
- }
+ Future unregister(String key) => _posthog.unregister(key);
- Future isFeatureEnabled(String key) {
- return _posthog.isFeatureEnabled(key);
- }
+ Future isFeatureEnabled(String key) => _posthog.isFeatureEnabled(key);
- Future reloadFeatureFlags() {
- return _posthog.reloadFeatureFlags();
- }
+ Future reloadFeatureFlags() => _posthog.reloadFeatureFlags();
Future group({
required String groupType,
required String groupKey,
Map? groupProperties,
- }) {
- return _posthog.group(
- groupType: groupType,
- groupKey: groupKey,
- groupProperties: groupProperties,
- );
- }
+ }) =>
+ _posthog.group(
+ groupType: groupType,
+ groupKey: groupKey,
+ groupProperties: groupProperties,
+ );
- Future