Skip to content

Commit

Permalink
feat(ios): initialize appsflyer
Browse files Browse the repository at this point in the history
  • Loading branch information
CatsJuice committed Nov 28, 2024
1 parent c95e6ec commit 0d7072d
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 43 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/release-mobile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/apps/ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ App/**/*.p8
*.zip
*.cer
App/fastlane/report.xml

afdevkey.plist
20 changes: 20 additions & 0 deletions packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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 */

Expand Down Expand Up @@ -111,6 +113,7 @@
9D90BE242CCB9876006677DB /* App */ = {
isa = PBXGroup;
children = (
E97774C02CF846AE009FF983 /* afdevkey.plist */,
9D90BE1A2CCB9876006677DB /* plugins */,
9D90BE1B2CCB9876006677DB /* AFFiNEViewController.swift */,
9D90BE1C2CCB9876006677DB /* AppDelegate.swift */,
Expand Down Expand Up @@ -144,6 +147,7 @@
504EC3011FED79650016851F /* Frameworks */,
504EC3021FED79650016851F /* Resources */,
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
06BC71AE56DF9F7D9910CD4F /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -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 */,
);
Expand All @@ -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;
Expand Down
127 changes: 95 additions & 32 deletions packages/frontend/apps/ios/App/App/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -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 {

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.
// 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 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.
}
AppsFlyerLib.shared().isDebug = true

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.
}
AppsFlyerLib.shared().appsFlyerDevKey = appsFlyerDevKey
AppsFlyerLib.shared().appleAppID = appleAppID

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.
}
AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)

AppsFlyerLib.shared().delegate = self
AppsFlyerLib.shared().deepLinkDelegate = self

print("Appflyer is ready")

return true
}

func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
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 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 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(_ 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)
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)
}
}
2 changes: 2 additions & 0 deletions packages/frontend/apps/ios/App/App/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -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>
10 changes: 10 additions & 0 deletions packages/frontend/apps/ios/App/App/afdevkey.plist
Original file line number Diff line number Diff line change
@@ -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>
1 change: 1 addition & 0 deletions packages/frontend/apps/ios/App/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down
28 changes: 17 additions & 11 deletions packages/frontend/apps/ios/App/Podfile.lock
Original file line number Diff line number Diff line change
@@ -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`)"
Expand All @@ -20,6 +24,7 @@ DEPENDENCIES:

SPEC REPOS:
trunk:
- AppsFlyerFramework
- CryptoSwift

EXTERNAL SOURCES:
Expand All @@ -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

0 comments on commit 0d7072d

Please sign in to comment.