From c0fa521e3612b6261638c19bd5976c2b5232948f Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Tue, 12 Apr 2022 13:04:46 -0700 Subject: [PATCH] Example plugins for more detailed cellular info --- .../project.pbxproj | 4 + .../SegmentUIKitExample/AppDelegate.swift | 1 + Examples/other_plugins/CellularCarrier.swift | 125 ++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 Examples/other_plugins/CellularCarrier.swift diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj index f0536cac..c297dc48 100644 --- a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 4602278C261F860100A9E913 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4602278A261F860100A9E913 /* Main.storyboard */; }; 4602278E261F860300A9E913 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4602278D261F860300A9E913 /* Assets.xcassets */; }; 46022791261F860300A9E913 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4602278F261F860300A9E913 /* LaunchScreen.storyboard */; }; + 463B27772805F4ED0090B83E /* CellularCarrier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 463B27762805F4ED0090B83E /* CellularCarrier.swift */; }; 46E3834C26582D9E00BA2502 /* UIKitScreenTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */; }; 46E3834D26582D9E00BA2502 /* ConsentTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834926582D9E00BA2502 /* ConsentTracking.swift */; }; 46E3834E26582D9E00BA2502 /* IDFACollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834A26582D9E00BA2502 /* IDFACollection.swift */; }; @@ -33,6 +34,7 @@ 46022790261F860300A9E913 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46022792261F860300A9E913 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 460227BC2620C02B00A9E913 /* SegmentUIKitExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SegmentUIKitExample-Bridging-Header.h"; sourceTree = ""; }; + 463B27762805F4ED0090B83E /* CellularCarrier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellularCarrier.swift; sourceTree = ""; }; 469F7AFA265D8D890038E773 /* SegmentUIKitExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SegmentUIKitExample.entitlements; sourceTree = ""; }; 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitScreenTracking.swift; sourceTree = ""; }; 46E3834926582D9E00BA2502 /* ConsentTracking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsentTracking.swift; sourceTree = ""; }; @@ -94,6 +96,7 @@ isa = PBXGroup; children = ( 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */, + 463B27762805F4ED0090B83E /* CellularCarrier.swift */, 46E73DA226F531320021042C /* NotificationTracking.swift */, 46E3834926582D9E00BA2502 /* ConsentTracking.swift */, 46E3834A26582D9E00BA2502 /* IDFACollection.swift */, @@ -206,6 +209,7 @@ 46E73DA326F531320021042C /* NotificationTracking.swift in Sources */, 46022787261F860100A9E913 /* SceneDelegate.swift in Sources */, 46E3834D26582D9E00BA2502 /* ConsentTracking.swift in Sources */, + 463B27772805F4ED0090B83E /* CellularCarrier.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift index bb966a22..bd3acece 100644 --- a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift @@ -18,6 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { Analytics.main.add(plugin: IDFACollection()) Analytics.main.add(plugin: UIKitScreenTracking()) Analytics.main.add(plugin: NotificationTracking()) + Analytics.main.add(plugin: CellularCarrier()) Analytics.support.add(plugin: ConsoleLogger(name: "support")) Analytics.support.add(plugin: ConsentTracking()) diff --git a/Examples/other_plugins/CellularCarrier.swift b/Examples/other_plugins/CellularCarrier.swift new file mode 100644 index 00000000..c4e64947 --- /dev/null +++ b/Examples/other_plugins/CellularCarrier.swift @@ -0,0 +1,125 @@ +// +// CellularCarrier.swift +// +// +// Created by Brandon Sneed on 4/12/22. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment +import CoreTelephony + +/** + An example plugin to retrieve cellular information. + + This plugin will add all carrier information to the event's context.network object if cellular + is currently in use. Example contents: + + { + "home": "T-Mobile", + "roaming": "AT&T", + "secondary": "Verizon", + } + + */ +class CellularCarrier: Plugin { + var type: PluginType = .enrichment + + var analytics: Analytics? + + func execute(event: T?) -> T? { + guard var workingEvent = event else { return event } + + if let isCellular: Bool = workingEvent.context?[keyPath: "network"], + isCellular, + let carriers = self.carriers + { + workingEvent.context?[keyPath: "network.carriers"] = carriers + } + + return workingEvent + } + + // done as a compute-once stored property; your use case may be different. + var carriers: [String: String]? = { + let info = CTTelephonyNetworkInfo() + if let providers = info.serviceSubscriberCellularProviders { + var results = [String: String]() + for (key, value) in providers { + if let carrier = value.carrierName, !carrier.isEmpty { + results[key] = value.carrierName + } + } + if !results.isEmpty { + return results + } + } + return nil + }() +} + + +/** + An example plugin to retrieve cellular information. + + This plugin will add primary ("home") carrier information to the event's context.network object if cellular + is currently in use. This mimics the operation of the analytics-ios SDK. + */ +class PrimaryCellularCarrier: Plugin { + var type: PluginType = .enrichment + + var analytics: Analytics? + + func execute(event: T?) -> T? { + guard var workingEvent = event else { return event } + + if let isCellular: Bool = workingEvent.context?[keyPath: "network"], + isCellular, + let carrier = self.carrier + { + workingEvent.context?[keyPath: "network.carriers"] = carrier + } + + return workingEvent + } + + // done as a compute-once stored property; your use case may be different. + var carrier: String? = { + let info = CTTelephonyNetworkInfo() + if let providers = info.serviceSubscriberCellularProviders { + let primary = providers["home"] + if let carrier = primary?.carrierName, !carrier.isEmpty { + return carrier + } + } + return nil + }() +} +