diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index 220d1c6d2..8c0b5b244 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0005580F2819C75700224BC6 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0005580E2819C75600224BC6 /* GoogleService-Info.plist */; }; 00069C77241C3B3B00FEE0EC /* ConvexHullViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00D4E8DB241AA18E002689DB /* ConvexHullViewController.swift */; }; 000FFFB426CB043200E3CE7E /* SetUpLocationDrivenGeotriggers.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 000FFFB326CB043200E3CE7E /* SetUpLocationDrivenGeotriggers.storyboard */; }; 000FFFB626CB044700E3CE7E /* SetUpLocationDrivenGeotriggersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000FFFB526CB044700E3CE7E /* SetUpLocationDrivenGeotriggersViewController.swift */; }; @@ -103,6 +104,7 @@ 00ADC3D12464DD3600A3B88D /* IdentifyRasterCellViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00ADC3D02464DD3600A3B88D /* IdentifyRasterCellViewController.swift */; }; 00ADC3D22464DDA200A3B88D /* IdentifyRasterCellViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00ADC3D02464DD3600A3B88D /* IdentifyRasterCellViewController.swift */; }; 00BA068525311B0D0039EF4D /* hydrography in Resources */ = {isa = PBXBuildFile; fileRef = 00BA068325311B0D0039EF4D /* hydrography */; settings = {ASSET_TAGS = (Hydrography, ); }; }; + 00BE7B38275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */; }; 00BE7B3E2764274C0012CE95 /* BrowseBuildingFloors.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 00BE7B3D2764274C0012CE95 /* BrowseBuildingFloors.storyboard */; }; 00BE7B402764275D0012CE95 /* BrowseBuildingFloorsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BE7B3F2764275D0012CE95 /* BrowseBuildingFloorsViewController.swift */; }; 00BE7B4127642A6C0012CE95 /* BrowseBuildingFloorsViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00BE7B3F2764275D0012CE95 /* BrowseBuildingFloorsViewController.swift */; }; @@ -1281,6 +1283,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0005580E2819C75600224BC6 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 000FFFB326CB043200E3CE7E /* SetUpLocationDrivenGeotriggers.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SetUpLocationDrivenGeotriggers.storyboard; sourceTree = ""; }; 000FFFB526CB044700E3CE7E /* SetUpLocationDrivenGeotriggersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUpLocationDrivenGeotriggersViewController.swift; sourceTree = ""; }; 00132100279B704200E89DD4 /* ShowDeviceLocationUsingIndoorPositioning.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ShowDeviceLocationUsingIndoorPositioning.storyboard; sourceTree = ""; }; @@ -1928,6 +1931,7 @@ buildActionMask = 2147483647; files = ( 006A786A262F9F15001D2A5E /* ArcGISToolkit in Frameworks */, + 00BE7B38275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2591,6 +2595,7 @@ C7E86C8E21751CFE001C65C3 /* Extensions */, 3E23AA071AFC2DE0002E2214 /* Content Display Logic */, 3E23A9E41AFC28F6002E2214 /* Info.plist */, + 0005580E2819C75600224BC6 /* GoogleService-Info.plist */, ); path = "arcgis-ios-sdk-samples"; sourceTree = ""; @@ -4850,6 +4855,7 @@ name = "ArcGIS Runtime SDK Samples"; packageProductDependencies = ( 006A7869262F9F15001D2A5E /* ArcGISToolkit */, + 00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */, ); productName = "arcgis-ios-sdk-samples"; productReference = 3E23A9E01AFC28F6002E2214 /* ArcGIS Runtime SDK Samples.app */; @@ -4949,6 +4955,7 @@ mainGroup = 3E23A9D71AFC28F6002E2214; packageReferences = ( 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */, + 00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, ); productRefGroup = 3E23A9E11AFC28F6002E2214 /* Products */; projectDirPath = ""; @@ -4993,6 +5000,7 @@ F1F62C4422E65E0900EFD599 /* militaryoverlay.geodatabase in Resources */, 3EBA254A1D300FB500AB0703 /* SimpleRenderer.storyboard in Resources */, 0083AA192628ED18003A28C8 /* ProgressViewController.xib in Resources */, + 0005580F2819C75700224BC6 /* GoogleService-Info.plist in Resources */, D97B7E5F1FD9BFE700E1239D /* Subdivisions.cpg in Resources */, F1EF67DD27E2AE480049FA9A /* QueryRelatedFeaturesNonSpatialTable.storyboard in Resources */, 3ED028B81B8E3A9800ACA70D /* SublayerVisibility.storyboard in Resources */, @@ -5841,8 +5849,11 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 100.15.0; - OTHER_LDFLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.esri.iOSSamples; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -5868,9 +5879,12 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 100.15.0; - OTHER_LDFLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples"; + MARKETING_VERSION = 100.145.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.esri.iOSSamples; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -5978,6 +5992,14 @@ minimumVersion = 100.15.0; }; }; + 00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 8.10.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -5986,6 +6008,11 @@ package = 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */; productName = ArcGISToolkit; }; + 00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */ = { + isa = XCSwiftPackageProductDependency; + package = 00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseAnalyticsWithoutAdIdSupport; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 3E23A9D81AFC28F6002E2214 /* Project object */; diff --git a/arcgis-ios-sdk-samples/AppDelegate.swift b/arcgis-ios-sdk-samples/AppDelegate.swift index 11562be96..6fb5a6c4d 100644 --- a/arcgis-ios-sdk-samples/AppDelegate.swift +++ b/arcgis-ios-sdk-samples/AppDelegate.swift @@ -14,6 +14,7 @@ import UIKit import ArcGIS +import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate { @@ -48,6 +49,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele // Enable/disable touches based on settings. self.setTouchPref() + // Set up Google Analytics 4. + self.setGoogleAnalyticsPref() + // Set license key and/or API key. application.license() @@ -94,6 +98,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele } } + // MARK: - Google Analytics settings + + func setGoogleAnalyticsPref() { + // Enable/disable GA based on settings. + let disableGoogleAnalytics = UserDefaults.standard.bool(forKey: "disableGoogleAnalytics") + if !disableGoogleAnalytics { + FirebaseApp.configure() + } + } + // MARK: - Appearance modification func modifyAppearance() { diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoriesCollectionViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoriesCollectionViewController.swift index dcf084ec4..4d0ba9a32 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoriesCollectionViewController.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoriesCollectionViewController.swift @@ -13,6 +13,7 @@ // limitations under the License. import UIKit +import Firebase class CategoriesCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { @IBOutlet private var collectionViewFlowLayout: UICollectionViewFlowLayout! @@ -98,12 +99,17 @@ class CategoriesCollectionViewController: UICollectionViewController, UICollecti let category = categories[indexPath.item] let controller = storyboard!.instantiateViewController(withIdentifier: "CategoryTableViewController") as! CategoryTableViewController controller.title = category.name + // Filter and display the favorited samples. if category.name == "Favorites" { controller.allSamples = categories .flatMap { $0.samples.filter(\.isFavorite) } controller.isFavoritesCategory = true } else { + // Google Analytics select category event. + Analytics.logEvent("select_category", parameters: [ + AnalyticsParameterContentType: category.name + ]) // Otherwise, show all samples. controller.allSamples = category.samples } diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoryTableViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoryTableViewController.swift index 055c887e8..893689c38 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoryTableViewController.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/CategoryTableViewController.swift @@ -13,6 +13,7 @@ // limitations under the License. import UIKit +import Firebase class CategoryTableViewController: UITableViewController { /// The samples to display in the table. Searching adjusts this value @@ -29,7 +30,7 @@ class CategoryTableViewController: UITableViewController { displayedSamples = allSamples } } - + var searchEngine: SampleSearchEngine? /// Tracks whether or not it is the favorites category. var isFavoritesCategory = false @@ -90,6 +91,11 @@ class CategoryTableViewController: UITableViewController { /// Responds to the selected sample being changed. private func selectedSampleDidChange() { if let sample = selectedSample { + // Google Analytics select sample event. + Analytics.logEvent("select_sample", parameters: [ + AnalyticsParameterContentType: sample.name + ]) + let indexPathForSample = indexPath(for: sample) if tableView.indexPathForSelectedRow != indexPathForSample { tableView.selectRow(at: indexPathForSample, animated: true, scrollPosition: .top) @@ -202,7 +208,18 @@ class CategoryTableViewController: UITableViewController { // Must use the presenting controller when opening from search results or else splitViewController will be nil. let presentingController: UIViewController? = searchEngine != nil ? presentingViewController : self - + + // If the sample is selected from search results, log the search term. + if let searchController = presentingViewController?.navigationItem.searchController, + searchController.isActive, + let searchTerm = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines), + !searchTerm.isEmpty { + // Google Analytics search event. + Analytics.logEvent(AnalyticsEventSearch, parameters: [ + AnalyticsParameterSearchTerm: searchTerm + ]) + } + let navController = UINavigationController(rootViewController: controller) // Don't use large titles on samples. @@ -261,8 +278,8 @@ extension CategoryTableViewController: UISearchResultsUpdating { expandedRowIndexPaths.removeAll() if searchController.isActive, - let query = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines), - !query.isEmpty { + let query = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines), + !query.isEmpty { displayedSamples = searchEngine.sortedSamples(matching: query) } else { displayedSamples = allSamples diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift index c981be9ae..459b5e1c7 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift @@ -14,6 +14,7 @@ import UIKit import WebKit +import Firebase class SourceCodeViewController: UIViewController, UIAdaptivePresentationControllerDelegate { /// The view to which the web view is added. @@ -56,6 +57,11 @@ class SourceCodeViewController: UIViewController, UIAdaptivePresentationControll setupToolbarTitle(filename, arrowPointingDown: true) let htmlString = htmlStringForContent(content) webView.loadHTMLString(htmlString, baseURL: URL(fileURLWithPath: Bundle.main.bundlePath)) + + // Google Analytics select code file event. + Analytics.logEvent("select_sourcefile", parameters: [ + AnalyticsParameterContentType: filename + ]) } } diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Custom BarButtonItem/FavoritesBarButtonItem.swift b/arcgis-ios-sdk-samples/Content Display Logic/Custom BarButtonItem/FavoritesBarButtonItem.swift index 7cd8ac344..7061cc65b 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Custom BarButtonItem/FavoritesBarButtonItem.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Custom BarButtonItem/FavoritesBarButtonItem.swift @@ -13,6 +13,7 @@ // limitations under the License. import UIKit +import Firebase final class FavoritesBarButtonItem: UIBarButtonItem { let sample: Sample @@ -35,6 +36,12 @@ final class FavoritesBarButtonItem: UIBarButtonItem { func toggleIsFavorite() { // Update the bool. sample.isFavorite.toggle() + if sample.isFavorite { + // Google Analytics set favorite event. + Analytics.logEvent("set_favorite", parameters: [ + AnalyticsParameterContentType: sample.name + ]) + } // Update the image. self.image = makeImage(isFavorite: sample.isFavorite) } diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Settings.bundle/Root.plist b/arcgis-ios-sdk-samples/Content Display Logic/Settings.bundle/Root.plist index 9d271b45b..437137aab 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Settings.bundle/Root.plist +++ b/arcgis-ios-sdk-samples/Content Display Logic/Settings.bundle/Root.plist @@ -22,6 +22,16 @@ DefaultValue + + Type + PSToggleSwitchSpecifier + Title + Disable Google Analytics + Key + disableGoogleAnalytics + DefaultValue + + diff --git a/arcgis-ios-sdk-samples/Info.plist b/arcgis-ios-sdk-samples/Info.plist index b491da806..33534dfea 100644 --- a/arcgis-ios-sdk-samples/Info.plist +++ b/arcgis-ios-sdk-samples/Info.plist @@ -45,6 +45,8 @@ CFBundleVersion $(CURRENT_PROJECT_VERSION) + GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED + ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS