Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.annotation.NonNull
import io.customer.customer_io.bridge.NativeModuleBridge
import io.customer.customer_io.bridge.nativeMapArgs
import io.customer.customer_io.bridge.nativeNoArgs
import io.customer.customer_io.geofence.CustomerIOGeofence
import io.customer.customer_io.location.CustomerIOLocation
import io.customer.customer_io.messaginginapp.CustomerIOInAppMessaging
import io.customer.customer_io.messagingpush.CustomerIOPushMessaging
Expand Down Expand Up @@ -54,10 +55,15 @@ class CustomerIOPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
modules = buildList {
add(CustomerIOPushMessaging(flutterPluginBinding))
add(CustomerIOInAppMessaging(flutterPluginBinding))
// Location module is optional - enabled via customerio_location_enabled gradle property
// Location module is optional - enabled via customerio_location_enabled gradle
// property. CIO_LOCATION_ENABLED also covers geofence (geofence implies location).
if (BuildConfig.CIO_LOCATION_ENABLED) {
add(CustomerIOLocation(flutterPluginBinding))
}
// Geofence module is optional - enabled via customerio_geofence_enabled gradle property
if (BuildConfig.CIO_GEOFENCE_ENABLED) {
add(CustomerIOGeofence(flutterPluginBinding))
}
}

// Attach modules to engine
Expand Down Expand Up @@ -231,15 +237,32 @@ class CustomerIOPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
)
}
}
// Configure location module based on config provided by customer app
args.getAs<Map<String, Any>>(key = "location")?.let { locationConfig ->
// Configure location module. Geofence implies location, so register location
// (with the app's config if given, otherwise defaults) whenever location or
// geofence is configured, since geofence relies on its location fixes. The build
// flags guard each block so the optional bridge classes (which reference native
// artifacts that are only linked when enabled) are never touched otherwise.
val locationConfig = args.getAs<Map<String, Any>>(key = "location")
val geofenceConfig = args.getAs<Map<String, Any>>(key = "geofence")
if (BuildConfig.CIO_LOCATION_ENABLED && (locationConfig != null || geofenceConfig != null)) {
modules.filterIsInstance<CustomerIOLocation>().forEach {
it.configureModule(
builder = this,
config = locationConfig,
config = locationConfig ?: emptyMap(),
)
}
}
// Configure geofence module (runs automatically once registered)
if (BuildConfig.CIO_GEOFENCE_ENABLED) {
geofenceConfig?.let { config ->
modules.filterIsInstance<CustomerIOGeofence>().forEach {
it.configureModule(
builder = this,
config = config,
)
}
}
}
}.build()

logger.info("Customer.io instance initialized successfully from app")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.customer.customer_io.geofence

import io.customer.customer_io.bridge.NativeModuleBridge
import io.customer.geofence.GeofenceModuleConfig
import io.customer.geofence.ModuleGeofence
import io.customer.sdk.CustomerIOBuilder
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodChannel

/**
* Flutter bridge for the geofence module. Geofence has no Flutter-facing methods —
* it runs automatically once registered — so this only wires the native module into
* the SDK builder. The reference to [ModuleGeofence] is isolated here so it is loaded
* only when the geofence dependency is bundled.
*
* Geofence depends on the location module; registration of location is handled by the
* plugin when geofence is configured.
*/
internal class CustomerIOGeofence(
pluginBinding: FlutterPlugin.FlutterPluginBinding,
) : NativeModuleBridge {
override val moduleName: String = "Geofence"
override val flutterCommunicationChannel: MethodChannel =
MethodChannel(pluginBinding.binaryMessenger, "customer_io_geofence")

override fun configureModule(builder: CustomerIOBuilder, config: Map<String, Any>) {
builder.addCustomerIOModule(ModuleGeofence(GeofenceModuleConfig.Builder().build()))
}
}
25 changes: 22 additions & 3 deletions ios/customer_io/Sources/customer_io/CustomerIOPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import UIKit
#if canImport(CioLocation)
import CioLocation
#endif
#if canImport(CioLocationGeofence)
import CioLocationGeofence
#endif

public class CustomerIOPlugin: NSObject, FlutterPlugin {
private var methodChannel: FlutterMethodChannel!
Expand Down Expand Up @@ -167,9 +170,18 @@ public class CustomerIOPlugin: NSObject, FlutterPlugin {
let sdkConfigBuilder = try SDKConfigBuilder.create(from: params)

#if canImport(CioLocation)
// Add location module to config builder if location config is provided
if let locationConfig = params["location"] as? [String: AnyHashable] {
let trackingModeValue = locationConfig["trackingMode"] as? String
let locationConfig = params["location"] as? [String: AnyHashable]
#if canImport(CioLocationGeofence)
let geofenceConfigured = params["geofence"] as? [String: AnyHashable] != nil
#else
let geofenceConfigured = false
#endif

// Add location module when location or geofence is configured. Geofence implies
// location: it relies on the location module's fixes, so register location (with
// the app's config if given, otherwise defaults) whenever geofence is enabled.
if locationConfig != nil || geofenceConfigured {
let trackingModeValue = locationConfig?["trackingMode"] as? String
let mode: LocationTrackingMode
switch trackingModeValue?.uppercased() {
case "OFF":
Expand All @@ -181,6 +193,13 @@ public class CustomerIOPlugin: NSObject, FlutterPlugin {
}
_ = sdkConfigBuilder.addModule(LocationModule(config: LocationConfig(mode: mode)))
}

#if canImport(CioLocationGeofence)
// Geofence runs automatically once registered; relies on the location module above.
if geofenceConfigured {
_ = sdkConfigBuilder.addModule(GeofenceModule())
}
#endif
#endif

CustomerIO.initialize(withConfig: sdkConfigBuilder.build())
Expand Down
Loading