Compare commits

...

1 Commits

Author SHA1 Message Date
Cats Juice
0d7072dd8e feat(ios): initialize appsflyer 2024-11-28 15:08:34 +08:00
8 changed files with 157 additions and 49 deletions

View File

@@ -123,6 +123,10 @@ jobs:
enableScripts: false
- name: Cap sync
run: yarn workspace @affine/ios cap sync
- name: Write afdevkey
working-directory: packages/frontend/apps/ios/App
run: |
echo "${{ env.APPSFLYER_DEV_KEY }}" | base64 --decode -o App/afdevkey.plist
- name: Signing By Apple Developer ID
uses: apple-actions/import-codesign-certs@v3
id: import-codesign-certs

View File

@@ -17,3 +17,5 @@ App/**/*.p8
*.zip
*.cer
App/fastlane/report.xml
afdevkey.plist

View File

@@ -19,6 +19,7 @@
9D90BE2E2CCB9876006677DB /* public in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE232CCB9876006677DB /* public */; };
C4C413792CBE705D00337889 /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
E93B276C2CED92B1001409B8 /* NavigationGesturePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93B276B2CED92B1001409B8 /* NavigationGesturePlugin.swift */; };
E97774C12CF846B9009FF983 /* afdevkey.plist in Resources */ = {isa = PBXBuildFile; fileRef = E97774C02CF846AE009FF983 /* afdevkey.plist */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -37,6 +38,7 @@
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
E93B276B2CED92B1001409B8 /* NavigationGesturePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationGesturePlugin.swift; sourceTree = "<group>"; };
E97774C02CF846AE009FF983 /* afdevkey.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = afdevkey.plist; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -111,6 +113,7 @@
9D90BE242CCB9876006677DB /* App */ = {
isa = PBXGroup;
children = (
E97774C02CF846AE009FF983 /* afdevkey.plist */,
9D90BE1A2CCB9876006677DB /* plugins */,
9D90BE1B2CCB9876006677DB /* AFFiNEViewController.swift */,
9D90BE1C2CCB9876006677DB /* AppDelegate.swift */,
@@ -144,6 +147,7 @@
504EC3011FED79650016851F /* Frameworks */,
504EC3021FED79650016851F /* Resources */,
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
06BC71AE56DF9F7D9910CD4F /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -196,6 +200,7 @@
9D90BE292CCB9876006677DB /* Assets.xcassets in Resources */,
9D90BE2A2CCB9876006677DB /* capacitor.config.json in Resources */,
9D90BE2B2CCB9876006677DB /* config.xml in Resources */,
E97774C12CF846B9009FF983 /* afdevkey.plist in Resources */,
9D90BE2D2CCB9876006677DB /* Main.storyboard in Resources */,
9D90BE2E2CCB9876006677DB /* public in Resources */,
);
@@ -204,6 +209,21 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
06BC71AE56DF9F7D9910CD4F /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-resources.sh\"\n";
showEnvVarsInLog = 0;
};
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

View File

@@ -1,49 +1,112 @@
import UIKit
import Capacitor
import AppsFlyerLib
import AppTrackingTransparency
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate, DeepLinkDelegate {
func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
print("onConversionDataSuccess: \(conversionInfo)")
}
func onConversionDataFail(_ error: any Error) {
print("onConversionDataFail: \(error)")
}
var window: UIWindow?
var window: UIWindow?
var appFlyerReady = false
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Get AppsFlyer preferences from .plist file
guard let propertiesPath = Bundle.main.path(forResource: "afdevkey", ofType: "plist"),
let properties = NSDictionary(contentsOfFile: propertiesPath) as? [String:String] else {
print("WARNING: Cannot find `afdevkey`")
return true
}
guard let appsFlyerDevKey = properties["appsFlyerDevKey"],
let appleAppID = properties["appleAppID"] else {
print("WARNING: Cannot find `appsFlyerDevKey` or `appleAppID` key")
return true
}
if appsFlyerDevKey.isEmpty || appleAppID.isEmpty {
return true
}
self.appFlyerReady = true
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
AppsFlyerLib.shared().isDebug = true
AppsFlyerLib.shared().appsFlyerDevKey = appsFlyerDevKey
AppsFlyerLib.shared().appleAppID = appleAppID
AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)
AppsFlyerLib.shared().delegate = self
AppsFlyerLib.shared().deepLinkDelegate = self
print("Appflyer is ready")
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
// if self.appFlyerReady {
// AppsFlyerLib.shared().start()
// if #available(iOS 14, *) {
// ATTrackingManager.requestTrackingAuthorization { (status) in
// switch status {
// case .denied:
// print("AuthorizationStatus is denied")
// case .notDetermined:
// print("AuthorizationStatus is notDetermined")
// case .restricted:
// print("AuthorizationStatus is restricted")
// case .authorized:
// print("AuthorizationStatus is authorized")
// @unknown default:
// fatalError("Invalid authorization status")
// }
// }
// }
// }
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
if self.appFlyerReady {
AppsFlyerLib.shared().handleOpen(url, options: options)
}
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
}

View File

@@ -63,5 +63,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>NSUserTrackingUsageDescription</key>
<string>AFFiNE needs access to track your activity on other apps and websites.</string>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>appsFlyerDevKey</key>
<string></string>
<key>appleAppID</key>
<string></string>
</dict>
</plist>

View File

@@ -20,6 +20,7 @@ target 'App' do
capacitor_pods
# Add your Pods here
pod 'CryptoSwift', '~> 1.8.3'
pod 'AppsFlyerFramework'
end
post_install do |installer|

View File

@@ -1,16 +1,20 @@
PODS:
- Capacitor (6.1.2):
- AppsFlyerFramework (6.15.3):
- AppsFlyerFramework/Main (= 6.15.3)
- AppsFlyerFramework/Main (6.15.3)
- Capacitor (6.2.0):
- CapacitorCordova
- CapacitorApp (6.0.1):
- CapacitorApp (6.0.2):
- Capacitor
- CapacitorBrowser (6.0.3):
- CapacitorBrowser (6.0.4):
- Capacitor
- CapacitorCordova (6.1.2)
- CapacitorKeyboard (6.0.2):
- CapacitorCordova (6.2.0)
- CapacitorKeyboard (6.0.3):
- Capacitor
- CryptoSwift (1.8.3)
DEPENDENCIES:
- AppsFlyerFramework
- "Capacitor (from `../../../../../node_modules/@capacitor/ios`)"
- "CapacitorApp (from `../../../../../node_modules/@capacitor/app`)"
- "CapacitorBrowser (from `../../../../../node_modules/@capacitor/browser`)"
@@ -20,6 +24,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- AppsFlyerFramework
- CryptoSwift
EXTERNAL SOURCES:
@@ -35,13 +40,14 @@ EXTERNAL SOURCES:
:path: "../../../../../node_modules/@capacitor/keyboard"
SPEC CHECKSUMS:
Capacitor: 679f9673fdf30597493a6362a5d5bf233d46abc2
CapacitorApp: 0bc633b4eae40a1f32cd2834788fad3bc42da6a1
CapacitorBrowser: aab1ed943b01c0365c4810538a8b3477e2d9f72e
CapacitorCordova: f48c89f96c319101cd2f0ce8a2b7449b5fb8b3dd
CapacitorKeyboard: 2700f9b18687be021e28b5a09b59eb151a46d5e0
AppsFlyerFramework: ad7ff0d22aa36c7f8cc4f71a5424e19b89ccb8ae
Capacitor: 1f3c7b9802d958cd8c4eb63895fff85dff2e1eea
CapacitorApp: 2a8c3a0b0814322e5e6e15fe595f02c3808f0f8b
CapacitorBrowser: ef0529d16cd8839281050c350e7bbee4f5c6d65f
CapacitorCordova: b33e7f4aa4ed105dd43283acdd940964374a87d9
CapacitorKeyboard: 460c6f9ec5e52c84f2742d5ce2e67bbc7ab0ebb0
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
PODFILE CHECKSUM: 1b0d3fe81862c0e9ce712ddd0c5a0accd0097698
PODFILE CHECKSUM: 1bf138ed644b943d4f8ccc008bbfdbf1cea13503
COCOAPODS: 1.16.2