AppsFlyer Unity Plugin

repository·master·Indexed 41 days ago

https://github.com/appsflyersdk/appsflyer-unity-plugin

A bridge between Unity applications and AppsFlyer mobile attribution and marketing analytics SDKs for Android and iOS. Version 7.0.2 introduces a JSON-RPC transport and async APIs using Awaitable, requiring Unity 2023.1 or newer. The plugin enables tracking of in-app events, attribution, and purchases, and utilizes the External Dependency Manager for Unity (EDM4U) to manage native dependencies.

Tokens
64.4K
Snippets
161
Records
239
Agent score
51%

What's inside AppsFlyer

  1. What is External Dependency Manager for Unity (EDM4U)?

    master

    External Dependency Manager for Unity (EDM4U), formerly known as Play Services Resolver or Jar Resolver, is a tool used to manage platform-specific dependencies in Unity projects.

    It is used for:

    • Android specific libraries: Managing AARs and other Android dependencies.
    • iOS CocoaPods: Managing iOS dependencies via CocoaPods.
    • Transitive dependency management: Handling versioning of dependencies that your dependencies require.
    • Package Manager (PM) Registries: Managing UPM registries.

    When to install it:

    • If you want to add and use iOS/Android dependencies directly in your project.
    • If you are using a plugin that depends on EDM4U but does not include it as a package dependency.
  2. Overview of the AppsFlyer Purchase Connector

    master

    The AppsFlyer ROI360 purchase connector is used to validate and report in-app purchase and subscription revenue events. It is part of the ROI360 measurement solution.

    Critical Usage Note: If you use the purchase connector, do not send in-app purchase events with revenue manually or execute validateAndLogInAppPurchase, as this will result in duplicate revenue reporting.

    Prerequisites:

    • ROI360 Subscription: Required to use this connector.
    • External Integration: Before implementing the connector, ROI360 must be integrated with Google Play and the App Store.
    • Unity Version: 2020.3 or higher.
    • iOS Requirements: StoreKit SDK v1 or v2 (StoreKit 2 requires iOS 15+), iOS 9+.
    • Android Requirements: Google Play Billing library version 7.x.x or 8.x.x.
    • Plugin Version: Unity AppsFlyer plugin 6.17.1 or higher.
  3. Understand the 7.x.x Async API and RPC Migration

    master

    Starting with version 7.x.x, the AppsFlyer Unity plugin has migrated its C#/native bridge to a JSON-RPC transport (defined in Assets/AppsFlyer/appsflyer-plugins-rpc-schema.json). This replaces the legacy AndroidJavaClass/DllImport bridge.

    Key Changes:

    • Async API: Most public methods that previously returned values synchronously are now async and return Awaitable<T> or Awaitable. This prevents blocking Unity's main thread during native round trips.
    • Renamed Methods: Several core APIs have been renamed to match the new async pattern. There are no backward-compatible aliases; you must update your call sites.
    • Removed UI Setup: The AppsFlyerObject.prefab UI-based setup has been removed. You must now use Manual Integration.
    • Session Ready Listener: A new API (AppsFlyer.OnSessionReady, registerSessionReadyListener(), etc.) allows you to defer start() until the native SDK reports it is ready.
    // Example of the new async pattern in 7.x.x
    await AppsFlyer.init(devKey, appID, gameObject);
    await AppsFlyer.start();
  4. Understand the AppsFlyer RPC Bridge Architecture

    master

    The AppsFlyer RPC Bridge provides a unified JSON-RPC dispatcher to facilitate communication between Unity and native iOS/Android modules.

    Key Components:

    • AppsFlyerRPCClient.cs: The new unified JSON-RPC dispatcher in C#.
    • AppsFlyerObjectScript.cs: Includes a new onRPCEvent() unified event handler.
    • iOS Implementation: Uses a single _afExecuteJson extern "C" entry point in AppsFlyerRPCWrapper.mm and may include AppsFlyerRPC.xcframework.
    • Android Implementation: Uses a new AppsFlyerRPCBridge.java JSON-RPC dispatcher within the Android wrapper.

    This architecture replaces individual P/Invoke functions and deprecated native methods with a single, structured RPC communication channel.

  5. Understand the RPC Schema Alignment in AppsFlyer Unity Plugin

    master

    The AppsFlyer Unity plugin has transitioned to a 100% RPC-driven architecture. This means the main AppsFlyer.cs class no longer uses a legacy bridge (IAppsFlyerNativeBridge, IAppsFlyerAndroidBridge, or IAppsFlyerIOSBridge) to communicate with native platforms. Instead, all public methods are strictly aligned with the Assets/AppsFlyer/appsflyer-plugins-rpc-schema.json schema.

    Key architectural changes:

    • Naming and Types: All Unity public methods, parameter names, and types now match the RPC schema exactly across both Android and iOS.
    • No Legacy Fallback: The new implementation does not call into legacy bridge files. Once the new implementation is confirmed, legacy files like AppsFlyerAndroid.cs, AppsFlyeriOS.cs, and the various IAppsFlyer...Bridge.cs interfaces are removed from the project.
    • Data Structures: Complex objects, such as in-app purchase payloads, now use nested structures (e.g., product and transaction objects) rather than flat key-value pairs.
  6. Understand iOS deep-link delivery architecture

    master

    The AppsFlyer Unity plugin uses a mixed architecture to deliver deep links on iOS, depending on the Unity Xcode project type:

    1. Classic (Objective-C AppDelegate) Project Type:

      • Deep links (including cold-start URL schemes and Universal Links) are delivered automatically via NSNotificationCenter observers and a narrow UnityAppController swizzle.
    2. Swift Xcode Project Type:

      • URL Schemes: Delivered automatically via NSNotificationCenter observers (e.g., kUnityOnOpenURL).
      • Universal Links: No automatic delivery path exists. You must manually bridge these calls from Swift to the plugin using AppsFlyer.continueUserActivity(url, activityType).
  7. Use the Session Ready Listener to coordinate start()

    master

    Instead of calling AppsFlyer.start() immediately after init(), use registerSessionReadyListener() to defer the start until the native SDK reports it is ready. This prevents racing start() against session evaluation.

    • Use AppsFlyer.registerSessionReadyListener() to subscribe to the readiness event.
    • Use AppsFlyer.unregisterSessionReadyListener() to stop listening.
    • Use AppsFlyer.isSessionReady() to poll the current state.
    AppsFlyer.OnSessionReady += OnSessionReadyHandler;   // subscribe first
    await AppsFlyer.init(devKey, appID, this);
    await AppsFlyer.registerSessionReadyListener();
    
    void OnSessionReadyHandler(object sender, EventArgs args)
    {
        AppsFlyer.OnSessionReady -= OnSessionReadyHandler;
        AppsFlyer.start();
    }
  8. RPC Request Envelope Structure

    master

    The Android plugin uses an RPC (Remote Procedure Call) mechanism to communicate with the SDK. Every request must follow a specific JSON envelope structure containing a method string and a params object.

    Default Behavior:

    • Fields omitted from params fall back to their defined defaults.
    • Most methods default awaitResponse to false.
    • Exceptions: validateAndLogInAppPurchase and generateInviteLink default awaitResponse to true.
    {
      "method": "method_name",
      "params": {
        "param_key": "param_value"
      }
    }
  9. Delay SDK initialization until Customer User ID is available

    master

    You can prevent the AppsFlyer SDK from functioning and discarding in-app events until a customerUserID is provided. This is useful when your user identity is determined asynchronously during app startup.

    1. Call waitForCustomerUserId(true) to put the SDK in a waiting state.
    2. Once the ID is available, call setCustomerIdAndStartSDK(string id) to provide the ID and trigger normal SDK activity.

    Warning: While waiting, all in-app events and other SDK API calls will be discarded.

    #if UNITY_ANDROID && !UNITY_EDITOR
            // 1. Tell SDK to wait
            AppsFlyer.waitForCustomerUserId(true);
    
            // ... later, once you have the ID ...
    
            // 2. Provide ID and start SDK
            AppsFlyer.setCustomerIdAndStartSDK("user_123");
    #endif