diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f185d8..1e4beff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,8 +53,8 @@ jobs: - name: Build and test app run: | pod install - xcodebuild build -workspace PushSDK.xcworkspace -scheme PushSDK -destination 'platform=iOS Simulator,OS=16.0,name=iPhone 13 Pro Max' - xcodebuild test -workspace PushSDK.xcworkspace -scheme PushSDKTests -destination 'platform=iOS Simulator,OS=16.0,name=iPhone 13 Pro Max' + xcodebuild build -workspace PushSDK.xcworkspace -scheme PushSDK -destination 'platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro Max' + xcodebuild test -workspace PushSDK.xcworkspace -scheme PushSDKTests -destination 'platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro Max' - name: Clean up keychain and provisioning profile if: ${{ always() }} diff --git a/PushSDK.podspec b/PushSDK.podspec index 921d69e..718d3b0 100644 --- a/PushSDK.podspec +++ b/PushSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "PushSDK" - s.version = "1.1.2" + s.version = "1.1.3" s.summary = "SDK for sending push messages to iOS devices." s.homepage = "https://github.com/GlobalMessageServices/BCS-GMS-SDK-IOS" @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.swift_version = ['3.0', '4.0', '4.2', '5.0', '5.1'] #s.source_files = 'PushSDKIOS/**/*.{swift}' - s.source_files = "Classes", "Classes/**/*.{h,m}", "PushSDK/*.{h,m}", "PushSDK/*.swift", "PushSDK/api", "PushSDK/core", "PushSDK/settings", "PushSDK/firebase", "PushSDK/models" + s.source_files = "Classes", "Classes/**/*.{h,m}", "PushSDK/*.{h,m}", "PushSDK/*.swift", "PushSDK/api", "PushSDK/core", "PushSDK/settings", "PushSDK/firebase", "PushSDK/models", "PushSDK/utils" diff --git a/PushSDK.xcodeproj/project.pbxproj b/PushSDK.xcodeproj/project.pbxproj index b0302c5..d290cfe 100644 --- a/PushSDK.xcodeproj/project.pbxproj +++ b/PushSDK.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 016F280528D2063D00F7D1A1 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016F280428D2063D00F7D1A1 /* Notifications.swift */; }; + 01C91A2B29797D3C00F3C3B6 /* InfoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C91A2A29797D3C00F3C3B6 /* InfoManager.swift */; }; 01FCADDA28C0C15E00D77FA4 /* PushSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01FCADD128C0C15E00D77FA4 /* PushSDK.framework */; }; 01FCADDF28C0C15E00D77FA4 /* PushSDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FCADDE28C0C15E00D77FA4 /* PushSDKTests.swift */; }; 01FCADE028C0C15E00D77FA4 /* PushSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FCADD428C0C15E00D77FA4 /* PushSDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -38,6 +39,7 @@ /* Begin PBXFileReference section */ 016F280428D2063D00F7D1A1 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = ""; }; + 01C91A2A29797D3C00F3C3B6 /* InfoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoManager.swift; sourceTree = ""; }; 01FCADD128C0C15E00D77FA4 /* PushSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PushSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 01FCADD428C0C15E00D77FA4 /* PushSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PushSDK.h; sourceTree = ""; }; 01FCADD928C0C15E00D77FA4 /* PushSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PushSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -82,6 +84,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 01C91A2929797D0A00F3C3B6 /* utils */ = { + isa = PBXGroup; + children = ( + 01C91A2A29797D3C00F3C3B6 /* InfoManager.swift */, + ); + path = utils; + sourceTree = ""; + }; 01FCADC728C0C15E00D77FA4 = { isa = PBXGroup; children = ( @@ -105,6 +115,7 @@ 01FCADD328C0C15E00D77FA4 /* PushSDK */ = { isa = PBXGroup; children = ( + 01C91A2929797D0A00F3C3B6 /* utils */, 01FCADED28C0C27D00D77FA4 /* api */, 01FCADEF28C0C27D00D77FA4 /* core */, 01FCADF728C0C27D00D77FA4 /* firebase */, @@ -374,6 +385,7 @@ 01FCAE0028C0C27D00D77FA4 /* JsonParser.swift in Sources */, 01FCADFC28C0C27D00D77FA4 /* PushAdapter.swift in Sources */, 01FCADFE28C0C27D00D77FA4 /* DataSaver.swift in Sources */, + 01C91A2B29797D3C00F3C3B6 /* InfoManager.swift in Sources */, 01FCAE0328C0C27D00D77FA4 /* FireBaseHelpers.swift in Sources */, 01FCAE0228C0C27D00D77FA4 /* PushSDK.swift in Sources */, 01FCADF928C0C27D00D77FA4 /* PushSDKFirebase.swift in Sources */, diff --git a/PushSDK.xcworkspace/xcuserdata/o.korniienko.xcuserdatad/UserInterfaceState.xcuserstate b/PushSDK.xcworkspace/xcuserdata/o.korniienko.xcuserdatad/UserInterfaceState.xcuserstate index ccb840d..2189892 100644 Binary files a/PushSDK.xcworkspace/xcuserdata/o.korniienko.xcuserdatad/UserInterfaceState.xcuserstate and b/PushSDK.xcworkspace/xcuserdata/o.korniienko.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PushSDK/PushSDK.swift b/PushSDK/PushSDK.swift index e952cb9..cc2cbaf 100644 --- a/PushSDK/PushSDK.swift +++ b/PushSDK/PushSDK.swift @@ -358,5 +358,60 @@ public class PushSDK { }) } + // get user's device data - OS, OS version, device model, UI language, region, time zone + public func getUserData()-> PushkUserData{ + PushKConstants.logger.debug("start function getUserData") + + let languageAndRegion = InfoManager.getLanguageAndRegion() + let userData = PushkUserData(deviceOS: PushKConstants.devOSName, + osVersion: PushKConstants.devOSVersion, + deviceModel: PushKConstants.deviceModel, + languageAndRegion: languageAndRegion, + timeZoneAbreviation: TimeZone.current.abbreviation() ?? "n/a", + timeZoneIdentifier: TimeZone.current.identifier) + PushKConstants.logger.debug("user data: \(userData.toString())") + return userData + } + + + // get country of location. user permission is required + public func locationCountry(handler: @escaping(String,String) -> Void){ + PushKConstants.logger.debug("start function locationCountry") + let infoManager = InfoManager() + Task{ + var countryCode = "n/a" + var countryName = "n/a" + if await infoManager.isLocationServicesEnaled(){ + let location = infoManager.locationManager.location + if location != nil{ + infoManager.geoCoder.reverseGeocodeLocation(location!) { (placemarks, error) in + guard let currentLocPlacemark = placemarks?.first else { + PushKConstants.logger.debug("location could not be determined") + infoManager.locationManager.stopMonitoringSignificantLocationChanges() + handler(countryCode, countryName) + return + } + + countryCode = currentLocPlacemark.isoCountryCode ?? "n/a" + countryName = currentLocPlacemark.country ?? "n/a" + PushKConstants.logger.debug("countryCode: \(countryCode)") + PushKConstants.logger.debug("countryName: \(countryName)") + infoManager.locationManager.stopMonitoringSignificantLocationChanges() + handler(countryCode, countryName) + } + }else{ + PushKConstants.logger.debug("location could not be determined") + infoManager.locationManager.stopMonitoringSignificantLocationChanges() + handler(countryCode, countryName) + } + + }else{ + PushKConstants.logger.debug("location service is not enabled") + infoManager.locationManager.stopMonitoringSignificantLocationChanges() + handler(countryCode, countryName) + } + + } + } } diff --git a/PushSDK/core/Notifications.swift b/PushSDK/core/Notifications.swift index b8557ff..861925c 100644 --- a/PushSDK/core/Notifications.swift +++ b/PushSDK/core/Notifications.swift @@ -39,7 +39,9 @@ class PushNotification { if(btnURL != "" && btnText != ""){ registerNotificationAction(btnText: btnText) content.categoryIdentifier = "pushKActionCategory" - content.userInfo = ["pushKActionButtonURL" : btnURL] + + let userInfoAction = userInfo.merging(["pushKActionButtonURL" : btnURL]){(current, _) in current} + content.userInfo = userInfoAction } diff --git a/PushSDK/models/DataStructures.swift b/PushSDK/models/DataStructures.swift index 2b57c9c..7ec20c3 100644 --- a/PushSDK/models/DataStructures.swift +++ b/PushSDK/models/DataStructures.swift @@ -220,3 +220,30 @@ public struct BranchStructObj { var pusUrlMessQueue: String var urlHttpMessHistory: String } + + +public struct PushkUserData { + var deviceOS: String + var osVersion: String + var deviceModel: String + var languageAndRegion: LanguageAndRegion + var timeZoneAbreviation: String + var timeZoneIdentifier: String + + public func toString() -> String { + return "PushkUserData(deviceOS: \(self.deviceOS),\n osVersion: \(self.osVersion),\n deviceModel: \(self.deviceModel),\n languageAndRegion: \(self.languageAndRegion.toString()),\n timeZoneAbreviation: \(self.timeZoneAbreviation),\n timeZoneIdentifier: \(self.timeZoneIdentifier))" + } +} + +public struct LanguageAndRegion{ + var deviceLanguage: String + var deviceLanguageEn: String + var isoLanguageCode: String + var isoRegion: String + var region: String + var regionEn: String + + public func toString() -> String { + return "LanguageAndRegion(deviceLanguage: \(self.deviceLanguage),\n deviceLanguageEn: \(self.deviceLanguageEn),\n isoLanguageCode: \(self.isoLanguageCode),\n isoRegion: \(self.isoRegion),\n region: \(self.region),\n regionEn: \(self.regionEn))" + } +} diff --git a/PushSDK/settings/Extensions.swift b/PushSDK/settings/Extensions.swift index 0af6f3c..2a70dc8 100644 --- a/PushSDK/settings/Extensions.swift +++ b/PushSDK/settings/Extensions.swift @@ -81,21 +81,35 @@ public extension UIDevice { case "iPhone13,2": return "iPhone 12" case "iPhone13,3": return "iPhone 12 Pro" case "iPhone13,4": return "iPhone 12 Pro Max" + case "iPhone14,4": return "iPhone 13 mini" + case "iPhone14,5": return "iPhone 13" + case "iPhone14,2": return "iPhone 13 Pro" + case "iPhone14,3": return "iPhone 13 Pro Max" + case "iPhone14,7": return "iPhone 14" + case "iPhone14,8": return "iPhone 14 Plus" + case "iPhone15,2": return "iPhone 14 Pro" + case "iPhone15,3": return "iPhone 14 Pro Max" + case "iPhone14,6": return "iPhone SE (3rd generation)" case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)" case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)" case "iPad6,11", "iPad6,12": return "iPad (5th generation)" case "iPad7,5", "iPad7,6": return "iPad (6th generation)" case "iPad7,11", "iPad7,12": return "iPad (7th generation)" + case "iPad11,6", "iPad11,7": return "iPad (8th generation)" + case "iPad12,1", "iPad12,2": return "iPad (9th generation)" + case "iPad13,18", "iPad13,19": return "iPad (10th generation)" case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" case "iPad5,3", "iPad5,4": return "iPad Air 2" case "iPad11,3", "iPad11,4": return "iPad Air (3rd generation)" case "iPad13,1", "iPad13,2": return "iPad Air (4th generation)" + case "iPad13,16", "iPad13,17": return "iPad Air (5th generation)" case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini" case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2" case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3" case "iPad5,1", "iPad5,2": return "iPad Mini 4" case "iPad11,1", "iPad11,2": return "iPad Mini 5" + case "iPad14,1", "iPad14,2": return "iPad mini (6th generation)" case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch) (1st generation)" @@ -104,6 +118,8 @@ public extension UIDevice { case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" case "iPad8,11", "iPad8,12": return "iPad Pro (12.9-inch) (4th generation)" + case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": return "iPad Pro (12.9-inch) (5th generation)" + case "iPad14,5", "iPad14,6": return "iPad Pro (12.9-inch) (6th generation)" case "AppleTV5,3": return "Apple TV" case "AppleTV6,2": return "Apple TV 4K" case "AudioAccessory1,1": return "HomePod" diff --git a/PushSDK/settings/PushConstants.swift b/PushSDK/settings/PushConstants.swift index 93ecb94..758334e 100644 --- a/PushSDK/settings/PushConstants.swift +++ b/PushSDK/settings/PushConstants.swift @@ -28,10 +28,12 @@ public struct PushKConstants { let kOSType = "ios" static let serverSdkVersion = "2.3" - static let sdkVersion = "1.1.2" + static let sdkVersion = "1.1.3" + static let devOSName = UIDevice.current.systemName static let devOSVersion = UIDevice.current.systemVersion static let deviceType = "\(UIDevice.current.model)" static let deviceType2 = "\(UIDevice.current.batteryLevel)" + static let deviceModel = UIDevice.modelName static let identifierForVendor = "\(String(describing: UIDevice.current.identifierForVendor))" static let localizedModel = "\(UIDevice.current.localizedModel)" static let kBundleID = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String diff --git a/PushSDK/utils/InfoManager.swift b/PushSDK/utils/InfoManager.swift new file mode 100644 index 0000000..e2b3a36 --- /dev/null +++ b/PushSDK/utils/InfoManager.swift @@ -0,0 +1,61 @@ +// +// InfoManager.swift +// PushSDK +// +// Created by o.korniienko on 19.01.23. +// + +import Foundation +import CoreLocation + +class InfoManager: NSObject, CLLocationManagerDelegate { + + + let locationManager = CLLocationManager() + let geoCoder = CLGeocoder() + + + override init() { + super.init() + locationManager.requestAlwaysAuthorization() + DispatchQueue.global().async { + if CLLocationManager.locationServicesEnabled(){ + self.locationManager.delegate = self + self.locationManager.startMonitoringSignificantLocationChanges() + } + + } + } + + + + static func getLanguageAndRegion()-> LanguageAndRegion{ + let preferLanguage = Locale.preferredLanguages.first ?? "n/a" + + if preferLanguage == "n/a"{ + return LanguageAndRegion(deviceLanguage: "n/a", deviceLanguageEn: "n/a", isoLanguageCode: "n/a", isoRegion: "n/a", region: "n/a", regionEn: "n/a") + } + let locale = NSLocale(localeIdentifier: preferLanguage) + let localeEn = NSLocale(localeIdentifier: "en_EN") + + let language = locale.localizedString(forLanguageCode: locale.languageCode) + let languageEn = localeEn.localizedString(forLanguageCode: locale.languageCode) + let region = locale.localizedString(forCountryCode: locale.countryCode ?? "en") + let regionEn = localeEn.localizedString(forCountryCode: locale.countryCode ?? "en") + + return LanguageAndRegion(deviceLanguage: language ?? "n/a", + deviceLanguageEn: languageEn ?? "n/a", + isoLanguageCode: locale.languageCode, + isoRegion: locale.countryCode ?? "n/a", + region: region ?? "n/a", + regionEn: regionEn ?? "n/a") + } + + + func isLocationServicesEnaled() async ->Bool{ + return CLLocationManager.locationServicesEnabled() + } + + + +} diff --git a/PushSDKTests/PushSDKTests.swift b/PushSDKTests/PushSDKTests.swift index 4478995..d2effcb 100644 --- a/PushSDKTests/PushSDKTests.swift +++ b/PushSDKTests/PushSDKTests.swift @@ -140,6 +140,19 @@ class PushSDKTests: XCTestCase { } + func testGetUserData(){ + let response = sdkInitPush.getUserData() + print(response) + } + + + func testGetLocation(){ + sdkInitPush.locationCountry{(code, name) in + print("code: \(code)") + print("name: \(name)") + } + } + } diff --git a/README.md b/README.md index 3e3b1ba..ad0d2f9 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ To open your project run $ open ProjectName.xcworkspace
More about Cocoapods and Podfile here - https://cocoapods.org, https://guides.cocoapods.org/using/the-podfile.html and https://guides.cocoapods.org/using/using-cocoapods.html. ### Add sdk to your project. -Last actual SDK version: 1.1.2
+Last actual SDK version: 1.1.3
To integrate PushSDK to your project with COCOAPODS (https://guides.cocoapods.org/using/the-podfile.html) add the next line in Podfile.
pod 'PushSDK', :git => 'https://github.com/GlobalMessageServices/BCS-GMS-SDK-IOS', :branch => 'main' @@ -273,6 +273,28 @@ public static func parseIncomingPush(message: [AnyHashable : Any]) -> PushKMess ``` *** +* get user/device data - iOS version, device model, language, time zoone, region (from user settings) +```swift +public func getUserData()-> PushkUserData +``` + +* get country of user current location. +```swift + public func locationCountry(handler: @escaping(String,String) -> Void) +``` +User permission is required to use this function. To prepare to ask the user for location permission add to Info.plist the following keys:
+Privacy - Location When In Use Usage Description
+Privacy - Location Always and When In Use Usage Description
+![photo1674487044](https://user-images.githubusercontent.com/46021248/214077180-437f00d4-d996-49ce-86c4-585b05b6473f.jpeg) +Example of using this function +```swift +pushSdk.locationCountry{(isoCountry, countryName) in + + print(isoCountry) + print(countryName) +} +``` + # SDK answers.
200 - Ok. All processed successfully