import Foundation import FirebaseRemoteConfig enum KMRemoteConfigFetchStatus: Int { case success case failure } let KMFirebaseRemateConfigRequestIsSuccessful = "KMFirebaseRemateConfigRequestIsSuccessful" let KMFirebaseRemateConfigFinishNoti = "KMFirebaseRemateConfigFinishNoti" typealias KMRemoteConfigFetchCompletion = (_ status: KMRemoteConfigFetchStatus, _ error: Error?) -> Void @objcMembers class KMKdanRemoteConfig: NSObject { private let kIsDisplayAdsKey = "isDisplayAds" private let kIsDisplayAdsEvaluateAfterKey = "isDisplayAdsEvaluateAfter" private let kDisplayAdsUrlConfigKey = "displayAdsUrl" private let kDisplayHouseAdsUrlConfigKey = "displayHouseAdsUrl" private let kRefreshAdsRateDayKey = "refreshAdsRate" private let kRefreshAdsRateDayEvaluateAfterKey = "refreshAdsRateEvaluateAfter" private let kRefreshAdsDateDayKey = "refreshAdsDate" private let kRefreshAdsDateDayEvaluateAfterKey = "refreshAdsDateEvaluateAfter" private let kCloseIntervalDateDayKey = "closeIntervalDate" private let kCloseIntervalDateDayEvaluateAfterKey = "closeIntervalDateEvaluateAfter" private let kAppEvaluateBeforeAdsCountKey = "appEvaluateBeforeAdsCount" private let kAppEvaluateAfterAdsCountKey = "appEvaluateAfterAdsCount" static let remoteConfig = KMKdanRemoteConfig() private var remoteConfigDatas: [String: Any] = [:] private var userInfo: [String: Any] = [:] private lazy var firebaseConfig: RemoteConfig = { let config = RemoteConfig.remoteConfig() let settings = RemoteConfigSettings() settings.minimumFetchInterval = 0 config.configSettings = settings #if VERSION_FREE config.setDefaults(fromPlist: "RemoteConfigDefaults") #else config.setDefaults(fromPlist: "ProRemoteConfigDefaults") #endif return config }() override init() { super.init() let mainBundleString = Bundle.main.bundleIdentifier ?? "" var dataPath: String? #if VERSION_DMG dataPath = Bundle.main.path(forResource: "DMGRemoteConfigDefaults", ofType: "plist") #else #if VERSION_FREE dataPath = Bundle.main.path(forResource: "RemoteConfigDefaults", ofType: "plist") #else dataPath = Bundle.main.path(forResource: "ProRemoteConfigDefaults", ofType: "plist") #endif #endif if let path = dataPath, let dict = NSDictionary(contentsOfFile: path) as? [String: Any] { self.userInfo = dict } } func fetch(completionHandler: @escaping KMRemoteConfigFetchCompletion) { let mainBundleString = Bundle.main.bundleIdentifier ?? "" let configuration = URLSessionConfiguration.default configuration.requestCachePolicy = .reloadIgnoringLocalCacheData configuration.urlCache = URLCache.shared let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" let params = "app_code=\(mainBundleString)&app_version=\(appVersion)&key=DisplayAds" var urlString = "http://store.pdfreaderpro.com:3018/api/get_config" #if DEBUG urlString = "http://test-store.kdan.cn:3018/api/get_config" #endif if let url = URL(string: "\(urlString)?\(params)") { var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let session = URLSession(configuration: configuration) let task = session.dataTask(with: request) { data, response, error in if let error = error { completionHandler(.failure, error) } else if let data = data { do { if let datas = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let displayAds = datas["data"] as? [String: Any] { #if VERSION_DMG if let dmg = displayAds["DisplayAds"] as? String { if let jsonData = dmg.data(using: .utf8), let dic = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any], let remoteConfigDatas = dic["dmg"] { self.remoteConfigDatas = remoteConfigDatas as! [String : Any] } } #else if let store = displayAds["DisplayAds"] as? String { if let jsonData = store.data(using: .utf8), let dic = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any], let remoteConfigDatas = dic["store"] { self.remoteConfigDatas = remoteConfigDatas as! [String : Any] } } #endif } completionHandler(.success, nil) } catch { completionHandler(.failure, error) } } NotificationCenter.default.post(name: Notification.Name(KMFirebaseRemateConfigRequestIsSuccessful), object: self, userInfo: nil) } task.resume() } } func fetchWithRemoteConfigCompletionHandler(completionHandler: @escaping RemoteConfigFetchCompletion) { let expirationDuration: TimeInterval = 0 // If your app is using developer mode, expirationDuration is set to 0, so each fetch will // retrieve values from the Remote Config service. // TimeInterval is set to expirationDuration here, indicating the next fetch request will use // data fetched from the Remote Config service, rather than cached parameter values, if cached // parameter values are more than expirationDuration seconds old. See Best Practices in the // README for more information. self.firebaseConfig.fetch(withExpirationDuration: expirationDuration) { status, error in if status == .success { self.firebaseConfig.activate { changed, error in // Handle activation completion if needed } } NotificationCenter.default.post(name: Notification.Name(KMFirebaseRemateConfigFinishNoti), object: self, userInfo: nil) completionHandler(status, error) } } func isDisplayAds() -> Bool { var isDisplayAds = userInfo[kIsDisplayAdsKey] as? Bool ?? true if let value = remoteConfigDatas[kIsDisplayAdsKey] as? Bool { isDisplayAds = value } return isDisplayAds } func isDisplayAdsEvaluateAfter() -> Bool { var isDisplayAds = userInfo[kIsDisplayAdsEvaluateAfterKey] as? Bool ?? true if let value = remoteConfigDatas[kIsDisplayAdsEvaluateAfterKey] as? Bool { isDisplayAds = value } return isDisplayAds } func displayHouseAdsUrl() -> String { var adsUrl = userInfo[kDisplayHouseAdsUrlConfigKey] as? String ?? "" if let value = remoteConfigDatas[kDisplayHouseAdsUrlConfigKey] as? String { adsUrl = value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" } return adsUrl } func displayAdsUrl() -> String { var adsUrl = userInfo[kDisplayAdsUrlConfigKey] as? String ?? "" if let value = remoteConfigDatas[kDisplayAdsUrlConfigKey] as? String { adsUrl = value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" } return adsUrl } func refreshAdsRate() -> Int { var adsRate = userInfo[kRefreshAdsRateDayKey] as? Int ?? 0 if let value = remoteConfigDatas[kRefreshAdsRateDayKey] as? String { adsRate = Int(value)! } return adsRate } func refreshAdsRateEvaluateAfter() -> Int { var adsRate = userInfo[kRefreshAdsRateDayEvaluateAfterKey] as? Int ?? 0 if let value = remoteConfigDatas[kRefreshAdsRateDayEvaluateAfterKey] as? String { adsRate = Int(value)! } return adsRate } func refreshAdsDate() -> Int { var adsDate = userInfo[kRefreshAdsDateDayKey] as? Int ?? 180 if let value = remoteConfigDatas[kRefreshAdsDateDayKey] as? String { adsDate = Int(value)! } return adsDate } func refreshAdsDateEvaluateAfter() -> Int { var adsDate = userInfo[kRefreshAdsDateDayEvaluateAfterKey] as? Int ?? 180 if let value = remoteConfigDatas[kRefreshAdsDateDayEvaluateAfterKey] as? String { adsDate = Int(value)! } return adsDate } func closeIntervalDate() -> Int { var intervalDate = userInfo[kCloseIntervalDateDayKey] as? Int ?? 0 if let value = remoteConfigDatas[kCloseIntervalDateDayKey] as? String { intervalDate = Int(value)! } return intervalDate } func closeIntervalDateEvaluateAfter() -> Int { var intervalDate = userInfo[kCloseIntervalDateDayEvaluateAfterKey] as? Int ?? 0 if let value = remoteConfigDatas[kCloseIntervalDateDayEvaluateAfterKey] as? String { intervalDate = Int(value)! } return intervalDate } func appEvaluateBeforeAdsCount() -> Int { var evaluateCount = userInfo[kAppEvaluateBeforeAdsCountKey] as? Int ?? 1 if let value = remoteConfigDatas[kAppEvaluateBeforeAdsCountKey] as? String { evaluateCount = Int(value)! } return evaluateCount } func appEvaluateAfterAdsCount() -> Int { var evaluateCount = userInfo[kAppEvaluateAfterAdsCountKey] as? Int ?? 1 if let value = remoteConfigDatas[kAppEvaluateAfterAdsCountKey] as? String { evaluateCount = Int(value)! } return evaluateCount } func showSDKRecommendInfo() -> Bool { guard firebaseConfig.lastFetchStatus == .success else { return false } return firebaseConfig["SDKRecommendKey"].boolValue } func showAPP_AveragePrice() -> Bool { guard firebaseConfig.lastFetchStatus == .success else { return false } return firebaseConfig["ShowAPP_AveragePrice"].boolValue } func showHelp_More_RecommendLink() -> Bool { guard firebaseConfig.lastFetchStatus == .success else { return false } return firebaseConfig["Help_More_Link_Recommend"].boolValue } }