| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- //
- // FlutterMethodChannelManager.swift
- // Runner
- //
- // Created by Destiny on 2025/5/8.
- //
- import Flutter
- import UIKit
- import StoreKit
- import AdServices
- class FlutterMethodChannelManager: NSObject {
-
- // 单例模式
- static let shared = FlutterMethodChannelManager()
-
- // 方法通道
- var keyboardChannel: FlutterMethodChannel?
-
- var retryCount = 0
-
- // 私有初始化方法
- private override init() {
- super.init()
- }
- // 设置方法通道
- func setupMethodChannels(controller: FlutterViewController) {
- // 创建键盘相关的方法通道
- keyboardChannel = FlutterMethodChannel(
- name: "keyboard_ios",
- binaryMessenger: controller.binaryMessenger)
-
- // 设置方法调用处理器
- keyboardChannel?.setMethodCallHandler { [weak self] (call, result) in
- guard let self = self else { return }
-
- switch call.method {
- case "saveSystemKeyboardInfo":
- if let args = call.arguments as? [String: Any],
- let info = args["info"] as? String {
- KeyboardSharedDataManager.shared.saveSystemkeyboard(info)
- result(true)
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- case "saveAuthToken":
- if let args = call.arguments as? [String: Any],
- let token = args["token"] as? String {
- KeyboardSharedDataManager.shared.saveToken(token)
- result(true)
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- case "clearAuthToken":
- KeyboardSharedDataManager.shared.clearAuthToken()
- result(true)
- case "saveIDFV":
- if let args = call.arguments as? [String: Any],
- let idfv = args["idfv"] as? String {
- KeyboardSharedDataManager.shared.saveInitIDFV(idfv)
- result(true)
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- case "saveIDFA":
- if let args = call.arguments as? [String: Any],
- let idfa = args["idfa"] as? String {
- KeyboardSharedDataManager.shared.saveInitIDFA(idfa)
- result(true)
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- case "isKeyboardAdded":
- let isAdd = self.isKeyboardEnabled()
- result(isAdd)
- case "isDefaultKeyboard":
- let isDefault = self.isCustomKeybroad()
- result(isDefault)
- case "openKeyboardGuide":
- KeyboardSharedDataManager.shared.saveIsShowGuide()
- result(true)
- case "isHasDiscount":
- if let args = call.arguments as? [String: Any],
- let appleGoodId = args["appleGoodId"] as? String {
- self.checkProductDiscount(appleGoodId: appleGoodId, completion: { hasDiscount in
- result(hasDiscount)
- })
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- case "initAttr":
- self.initAttribution()
- case "addASAPayReport":
- if let args = call.arguments as? [String: Any],
- let price = args["price"] as? Double {
- AsaManager.shared.addEventAttribution(eventDict: ["event_name": "pay", "event_val": price])
- } else {
- result(FlutterError(code: "INVALID_ARGUMENTS", message: "无效的参数", details: nil))
- }
- default:
- result(FlutterMethodNotImplemented)
- }
- }
- }
-
- // 是否添加键盘
- func isKeyboardEnabled() -> Bool {
-
- // 获取系统中已安装的键盘列表
- let keyboards = UserDefaults.standard.dictionaryRepresentation()
- .filter { $0.key.contains("Keyboard") }
- if let keyboardList = keyboards["AppleKeyboards"] as? [String] {
-
- let keyboardBundleId = "com.qihuan.zhuiaijianpan.AiKeyboard"
- let isAdded = keyboardList.contains(keyboardBundleId)
- return isAdded
- }
- return false
- }
-
- // 是否为默认键盘
- func isCustomKeybroad() -> Bool {
-
- let currentKeyboardName = (((UITextInputMode.activeInputModes as NSArray).filtered(using: NSPredicate(format: "isDisplayed = YES"))).last as? NSObject)?.value(forKey: "extendedDisplayName") as? String
-
- let infoDictionary = Bundle.main.infoDictionary!
- let appDisplayName = infoDictionary["CFBundleDisplayName"] as? String
-
- return currentKeyboardName == appDisplayName
- }
-
- }
- extension FlutterMethodChannelManager {
-
- func initAttribution() {
-
- if #available(iOS 14.3, *) {
- do {
- let appleAttributionToken = try AAAttribution.attributionToken()
- // 尝试获取归因信息
- getASA(token: appleAttributionToken)
- } catch let error {
- print("Error fetching attribution token: \(error.localizedDescription)")
- }
- }
- }
-
- // 开始获取归因结果
- func getASA(token: String) {
-
- guard retryCount < 3 else { return }
-
- let configuration = URLSessionConfiguration.default
- let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
- let asaUrl = URL(string: "https://api-adservices.apple.com/api/v1/")!
-
- var request = URLRequest(url: asaUrl)
- request.httpMethod = "POST"
- request.addValue("application/json", forHTTPHeaderField: "Content-Type")
- request.httpBody = token.data(using: .utf8)
-
- let task = session.dataTask(with: request) { data, response, error in
- if let error = error {
- print("sendASAToken error = \(error)")
- // 5秒后重试
- DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
- self.getASA(token: token)
- }
- return
- }
-
- guard let data = data, let payloadDic = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
- print("sendASAToken error payload = nil")
- // 5秒后重试
- DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
- self.getASA(token: token)
- }
- return
- }
-
- print("sendASAToken payload = \(payloadDic)")
-
- if let attribution = payloadDic["attribution"] {
- UserDefaults.standard.set(payloadDic, forKey: "ASA_ATTRIBUTION_PAYLOAD")
- UserDefaults.standard.synchronize()
-
- // 调用奇异果数据上报接口
- let appSaManager = AsaManager.shared
- appSaManager.addAttributionReport { isSuccess in
- print("asaReportWithCompletion = ", isSuccess)
-
- if isSuccess {
- let isRegister = UserDefaults.standard.bool(forKey: "isRegisterKey")
- if !isRegister {
- AsaManager.shared.addEventAttribution(eventDict: ["event_name": "active", "event_val": 1])
- AsaManager.shared.addEventAttribution(eventDict: ["event_name": "register", "event_val": 1])
- UserDefaults.standard.setValue(true, forKey: "isRegisterKey")
- }
- }
- }
- }
- }
- task.resume()
- retryCount += 1
- }
- }
- extension FlutterMethodChannelManager {
-
- private func checkProductDiscount(appleGoodId: String, completion: @escaping (Bool) -> Void) {
-
- if #available(iOS 15.0, *) {
- Task {
- do {
- // print("开始请求产品信息 (StoreKit 2)")
- let products = try await Product.products(for: [appleGoodId])
- print("成功获取产品信息: \(products.count) 个产品")
- if let product = products.first {
- // 检查是否有优惠
- var hasDiscount = await product.subscription?.isEligibleForIntroOffer ?? false
-
- DispatchQueue.main.async {
- completion(hasDiscount)
- }
- } else {
- print("未找到产品")
- DispatchQueue.main.async {
- completion(false)
- }
- }
- } catch {
- print("获取产品失败 (StoreKit 2): \(error)")
- DispatchQueue.main.async {
- completion(false)
- }
- }
- }
- }
-
- // // 使用StoreKit查询商品信息
- // let request = SKProductsRequest(productIdentifiers: [appleGoodId])
- // request.delegate = ProductRequestDelegate(completion: { product in
- // if let product = product {
- // // iOS 12.2及以上版本支持促销优惠
- // if #available(iOS 12.2, *) {
- // // 检查商品是否有促销优惠
- // let hasDiscount = product.discounts.count > 0
- // completion(hasDiscount)
- // } else {
- // completion(false)
- // }
- // } else {
- // completion(false)
- // }
- // })
- // request.start()
- }
- }
- // 处理StoreKit产品请求的代理
- class ProductRequestDelegate: NSObject, SKProductsRequestDelegate {
-
- private let completion: (SKProduct?) -> Void
- init(completion: @escaping (SKProduct?) -> Void) {
- self.completion = completion
- super.init()
- }
- func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
- if let product = response.products.first {
- completion(product)
- } else {
- completion(nil)
- }
- }
- func request(_ request: SKRequest, didFailWithError error: Error) {
- print("商品请求失败: \(error.localizedDescription)")
- completion(nil)
- }
- }
|