Xamarin iOS

NugetNuget

📘

iOS 14 实施

为了帮助您全面管理用户体验,Branch SDK 将不会触发 IDFA 许可弹窗。

然而,如果您选择触发这一弹窗,在可行的情况下,Branch 仍然可以收集并使用 IDFA。

了解更多

❗️

iOS 11.2 上 Universal Links 行为不一致

After updating a device to iOS 11.2, we found that the app's AASA file is no longer downloaded reliably onto your user’s device after an app install. As a result, clicking on Universal links will no longer open the app consistenly. You can set forced uri redirect mode on your Branch links to open the app with URI schemes. View details of the issue on the Apple Bug report.

配置 Branch

安装 Branch

NuGet

The Branch Xamarin SDK is available as a NuGet package. The Branch NuGet package must be added to each of the Xamarin projects that will use Branch methods.

要将 Branch NuGet 包添加到项目中:

  1. 右键点击每个项目,然后选择 Add > Add NuGet Packages
  2. Find the Branch Xamarin SDK package and add it to the project

配置应用

为该应用创建 Apple 设备配置配置文件

  1. 打开 Xcode 并创建一个与 Xamarin iOS 项目同名的新项目
  2. 在 Xcode 项目的General选项卡上,验证应用区分大小写的 Bundle ID 正确无误,然后选择适当的团队(请确保在此处解决所有错误)
  3. 选择Capabilities标签并启用Associated Domains授权
  4. Create 'applinks:' entries for the Branch link domain and the alternate link domain (the link domain can be found at the bottom of the Branch dashboard's Link Settings page). For example, the entries for an app with the default link domain 'testiosapp.app.link' would be:
    applinks:testiosapp.app.link
    applinks:testiosapp-alternate.app.link
  5. 使用 Xcode 在 iOS 设备上运行此新创建的应用。这将在该设备上创建并安装具有适当 entitlement 的预配配置文件。
  6. 关闭 Xcode

在 Branch 操作后台 (Dashboard)上输入应用的设置

  1. On the Link Settings page, check the I have an iOS App checkbox
  2. Enter the app's URI Scheme in the iOS URI Scheme field (for an app with the URI Scheme testbed-xamarin, for example, the entry would be: testbed-xamarin://
  3. Apple Store Search字段中输入应用的 Apple Store 名称(如果该应用尚未在 App Store 上提供,请选择Custom URL并输入适当网站的 URL 作为占位符—无需输入确切的 URL)
  4. 选中Enable Universal Links复选框
  5. Enter the app's case-sensitive Bundle Identifier and Apple App Prefix as shown on the Apple Developer Portal

配置 Xamarin 项目的 Info.plist 文件

  1. 打开Info.plist文件
  2. Enter the app's Bundle Identifier from the Apple Developer Portal in the Bundle Identifier field. IMPORTANT: this field will automatically be populated with an all-lowercase value by Xamarin. The value is in fact case sensitive and must match the value in the Apple Developer Portal precisely.
  3. 点击Advanced标签
  4. URL Types部分中,点击Add URL Type
    Identifier:Branch Scheme
    URL Schemes: {应用的URI Scheme—例如 “testiosapp”} Role:编辑器

图片图片

配置 Xamarin 项目的 Associated Domain 权限

  1. 打开Entitlements.plist文件并浏览到关联域(Associated Domain)
  2. 为应用的链接域及其备用链接域创建条目。 TestBed-Xamarin 应用的条目为:
    applinks:testiosapp.app.link
    applinks:testiosapp-alternate.app.link

图片图片

更新项目的签名身份和配置文件

  1. 右键点击 iOS 项目,然后选择 Options
  2. 选择 iOS Bundle Signing
  3. Signing IdentityProvisioning Profile values设置为将 Provisioning Profile 部署到上述设备时使用的值

初始化 Branch

Branch initialization occurs within the FinishedLaunching method of the AppDelegate.cs file. Branch calls are also required in the OpenUrlContinueUserActivity, and ReceiveRemoteNotification methods to ensure that Branch link information is handled properly whenever the app becomes active.

Whenever the app becomes active, the Branch SDK will reach out to the Branch back end to retrieve any available link parameters. If the app became active due to a click on a Branch link, the link data will be returned in the InitSessionComplete method. This is where any deep link routing logic should reside. Any error in retrieving Branch link data from the back end will returned in the SessionRequestError method.

// AppDelegate.cs

using Foundation;
using UIKit;
using BranchXamarinSDK;
using BranchXamarinSDK.iOS;
using System;

namespace TestiOSApp.iOS
{
    [Register("AppDelegate")]
    public class AppDelegate : UIApplicationDelegate, IBranchBUOSessionInterface
    {
        public override UIWindow Window
        {
            get;
            set;
        }

        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
        {
            // Debug mode - set to 'false' before releasing to production
            BranchIOS.Debug = true;
            BranchIOS.Init("key_live_cgEguO4UiDJSL4HIyTu85dkkDAdz38ER", launchOptions, this);

            return true;
        }

        // Called when the app is opened via URI scheme
        public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
        {
            return BranchIOS.getInstance().OpenUrl(url);
        }

        // Called when the app is opened from a Universal Link
        public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity,
                      UIApplicationRestorationHandler completionHandler)
        {
            return BranchIOS.getInstance().ContinueUserActivity(userActivity);
        }

        // Called when the app receives a push notification
        public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
        {
            BranchIOS.getInstance().HandlePushNotification(userInfo);
        }

        // Called when the Branch initialization is completed
        // Put deep-linking logic in this method
        public void InitSessionComplete(BranchUniversalObject buo, BranchLinkProperties blp)
        {
            NSObject[] keys = {
                NSObject.FromObject("+is_first_session")
            };

            NSObject[] values = { NSObject.FromObject(0) };
            if (buo.metadata.ContainsKey("+is_first_session"))
            {
                values[0] = NSObject.FromObject(buo.metadata["+is_first_session"]);
            }

            NSDictionary nsData = NSDictionary.FromObjectsAndKeys(values, keys);
        }

        // Called when there is an error initializing Branch
        public void SessionRequestError(BranchError error)
        {
            Console.WriteLine("Branch error: " + error.ErrorCode);
            Console.WriteLine(error.ErrorMessage);
        }

    }
}

使用 Xamarin 表单配置 Branch

使用 NuGet 添加 Branch SDK

The Branch Xamarin SDK is available as a NuGet package. The Branch NuGet package must be added to each of the Xamarin projects that will use Branch methods.

  1. 右键点击每个项目,然后选择 Add > Add NuGet Packages
  2. Find the Branch Xamarin SDK package and add it to the project

创建用于 Branch 会话处理的类

Branch 异步初始化,通过对 Branch 的网络调用返回 Branch link 参数。如果初始化成功,则将调用 InitSessionComplete 方法。如果初始化失败,则将调用SessionRequestError 方法。深度链接路由逻辑应位于 InitSessionComplete 方法中。

  1. 右键点击C#项目,然后选择 Add > New File...
  2. 选择: General > Empty Class
  3. 重命名文件: TestXamarinFormsApp.cs
  4. 输入以下代码(将 “TestXamarinFormsApp” 替换为应用的实际名称):
using BranchXamarinSDK;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;

namespace TestXamarinFormsApp
{
    public class TestXamarinFormsApp : Application, IBranchSessionInterface
    {

        public TestXamarinFormsApp()
        {
        }

        #region IBranchSessionInterface implementation

        public void InitSessionComplete(Dictionary<string, object> data)
        {
        }

        public void CloseSessionComplete()
        {
        }

        public void SessionRequestError(BranchError error)
        {
        }

        #endregion
    }
}

创建一个用于处理链接数据的类

Branch 将链接数据存储在称为Branch Universal ObjectBUO

  1. 右键点击C#项目,然后选择 Add > New File...
  2. 选择: General > Empty Class
  3. 重命名文件: TestXamarinFormsAppBUO.cs
  4. 输入以下代码(将 “TestXamarinFormsApp” 替换为应用的实际名称):
using BranchXamarinSDK;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;

namespace TestXamarinFormsApp
{
    public class TestXamarinFormsAppBUO : Application, IBranchBUOSessionInterface
    {

        public TestXamarinFormsAppBUO()
        {
        }

        #region IBranchBUOSessionInterface implementation

        public void InitSessionComplete(BranchUniversalObject buo, BranchLinkProperties blp)
        {
        }

        public void SessionRequestError(BranchError error)
        {
        }

        #endregion
    }
}

为该应用创建 Apple 设备配置配置文件

  1. 打开 Xcode 并创建一个与 Xamarin iOS 项目同名的新项目
  2. 在 Xcode 项目的General标签上,输入应用的 Bundle ID 并选择适当的团队(请确保在此处解决所有错误)
  3. 选择Capabilities标签并启用Associated Domains授权
  4. Create 'applinks:' entries for the Branch link domain assigned to the app (the link domain can be found at the bottom of the Branch dashboard's Link Settings page). For example, the entries for the app TestXamarinFormsApp would be:
    applinks:testxamarinformsapp.app.link
    applinks:testxamarinformsapp-alternate.app.link
  5. 使用 Xcode 在 iOS 设备上运行此新创建的应用。这将在该设备上创建并安装具有适当 entitlement 的预配配置文件。
  6. 关闭 Xcode

在 Branch 操作后台 (Dashboard)上输入应用的设置

  1. On the Link Settings page, check the I have an iOS App checkbox
  2. Enter the app's URI Scheme in the iOS URI Scheme field (for an app with the URI Scheme testxamarinformsapp, for example, the entry would be: testxamarinformsapp://
  3. Apple Store Search字段中输入应用的 Apple Store 名称(如果该应用尚未在 App Store 上提供,请选择Custom URL并输入适当网站的 URL 作为占位符—无需输入确切的 URL)
  4. 选中Enable Universal Links复选框
  5. Enter the app's Bundle Identifier and Apple App Prefix as shown on the Apple Developer Portal

配置 Xamarin 项目的 Info.plist 文件

  1. 打开Info.plist文件
  2. Enter the app's Bundle Identifier from the Apple Developer Portal in the Bundle Identifier field. IMPORTANT: this field will automatically be populated with an all-lowercase value by Xamarin. The value is in fact case sensitive and must match the value in the Apple Developer Portal precisely.
  3. 点击Advanced标签
  4. URL Types部分中,点击Add URL Type
    Identifier:Branch Scheme
    URL Schemes: {该应用的 URI Scheme-例如 'testxamarinformsapp'}
    Role:编辑器

图片图片

配置 Xamarin 项目的 Associated Domain 权限

  1. 打开Entitlements.plist文件并浏览到Associated Domains (如果此文件尚不存在,请进行创建)
  2. 为应用的链接域及其备用链接域创建条目。 TestBed-Xamarin 应用的条目为:
    applinks:testxamarinformsapp.app.link
    applinks:testxamarinformsapp-alternate.app.link

图片图片

将 Branch 调用添加到 AppDelegate.cs 文件

To ensure that the Branch SDK initializes when the app starts and can retrieve link parameters whenever the app becomes active, Branch initialization occurs within the FinishedLaunching method of the AppDelegate.cs file. Branch calls are also required in the OpenUrl, ContinueUserActivity, and ReceiveRemoteNotification methods to ensure that Branch link information is handled properly whenever the app becomes active. The AppDelegate.cs file should look like this:

using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using UIKit;
using BranchXamarinSDK;
using TestXamarinFormsApp;

namespace TestXamarinFormsApp.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            // Debug mode - set to 'false' before releasing to production
            BranchIOS.Debug = true;

            TestXamarinFormsAppBUO appBUO = new TestXamarinFormsAppBUO();
            BranchIOS.Init("key_live_liAnF8k7gZUEZv76Rt9a4bffAzlC5zVW", options, appBUO);
            LoadApplication(appBUO);

            return base.FinishedLaunching(app, options);
        }

        // Called when the app is opened via URI scheme
        public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
        {
            return BranchIOS.getInstance().OpenUrl(url);
        }

        // Called when the app is opened from a Universal Link
        public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
        {
            return BranchIOS.getInstance().ContinueUserActivity(userActivity);
        }

        // Called when the app receives a push notification
        public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
        {
            BranchIOS.getInstance().HandlePushNotification(userInfo);
        }
    }
}

实现功能

创建内容参考

BranchUniversalObject universalObject = new BranchUniversalObject();
universalObject.canonicalIdentifier = "id12345";
universalObject.title = "id12345 title";
universalObject.contentDescription = "My awesome piece of content!";
universalObject.imageUrl = "https://s3-us-west-1.amazonaws.com/branchhost/mosaic_og.png";
universalObject.metadata.AddCustomMetadata("foo", "bar");

创建深度链接

BranchLinkProperties linkProperties = new BranchLinkProperties();
linkProperties.tags.Add("tag1");
linkProperties.tags.Add("tag2");
linkProperties.feature = "sharing";
linkProperties.channel = "facebook";
linkProperties.controlParams.Add("$desktop_url", "http://example.com");

Branch.GetInstance().GetShortURL(callback,
                                  universalObject,
                                  linkProperties);

分享深度链接

  • 生成 Branch 深度链接,并通过用户选择的渠道对其进行标签

  • Needs a Create content reference

  • 需要[创建链接参考]/developers-hub/docs/ios-advanced-features#section-create-link-reference)

  • Uses Deep Link Properties

Branch.GetInstance().ShareLink (callback,
           universalObject,
           linkProperties,
           message)

读取深度链接

  • 从深度链接中提取 Branch 数据

  • 最佳做法是从 listener (to prevent a race condition)

  • Returns deep link properties

// latest
Dictionary<string, object> sessionParams = Branch.GetInstance().GetLatestReferringParams();

// first
Dictionary<string, object> installParams = Branch.GetInstance().GetFirstReferringParams();

NativeLink™ Deferred Deep Linking (iOS Only)

  • Use iOS pasteboard to enable deferred deep linking via Branch NativeLink™

🚧

先决条件

Make sure you are on v7.1.2+

To use this feature you must:

Implement one of the pasteboard opt-in options in the native iOS SDK code.

追踪用户

  • Sets the identity of a user (ID, UUID, etc) for events, deep links, and referrals

  • Validate with the Branch Dashboard

Branch branch = Branch.GetInstance ();
branch.SetIdentity("the user id", this);  // Where this implements IBranchIdentityInterface
branch.Logout(this); // Where this implements IBranchIdentityInterface

追踪 Commerce Event

  • Commerce Event 描述客户与您的产品进行交互并通过购买进行转化相关的事件。这些事件包括添加付款信息,购买,查看产品等。如果启用了 Branch Universal Ads(全域广告归因),这些事件将自动映射到部分广告合作伙伴。首先为与您重新追踪的事件相关联的每个产品创建一个 Branch Universal Object。

  • 从那里,将 Branch Universal Object 添加到追踪的事件,并使用正确的预定义常量。例如,下面的代码片段用于追踪用户何时将其添加到购物车,但只需将该常量替换为另一个常量即可追踪不同的事件。

  • 有关货币和汇率的说明:
    如果您在没有货币的情况下追踪 Commerce Event,则我们假设它们是美元。如果您使用非美元的货币追踪 Commerce Event,我们将使用最近的汇率将指定的收入转化为美元。

  • 由于所有单位均为美元,因此您可以轻松地在操作后台 (Dashboard)上查看许多国家和货币的收入。定期从 openexchangerates.org 提取汇率,并且通常在实时汇率的一小时内。如果通过 Webhooks 或 Exports查看原始的 Branch 事件,则可以看到所使用的汇率。

  • Validate with the Branch Dashboard

BranchUniversalObject universalObject = new BranchUniversalObject();
universalObject.canonicalIdentifier = "id12345";
universalObject.canonicalUrl = "https://branch.io/item/id12345";
universalObject.title = "Item 12345";
universalObject.contentDescription = "My awesome piece of content!";
universalObject.imageUrl = "https://s3-us-west-1.amazonaws.com/branchhost/mosaic_og.png";

universalObject.metadata.price = (float)23.20;
universalObject.metadata.quantity = 1;
universalObject.metadata.sku = "1994329302";
universalObject.metadata.productName = "my_product_name1";
universalObject.metadata.productBrand = "my_product_brand1";
universalObject.metadata.productCategory =                      BranchProductCategory.APPAREL_AND_ACCESSORIES;
universalObject.metadata.productVariant = "XL";
universalObject.metadata.condition = BranchCondition.NEW;
universalObject.metadata.AddCustomMetadata("foo", "bar");

BranchEvent branchCommerceEvent = new BranchEvent(BranchEventType.PURCHASE);
branchCommerceEvent.SetAlias("new_user_purchase");
branchCommerceEvent.AddContentItem(universalObject); 
branchCommerceEvent.SetRevenue((float)1.5);
branchCommerceEvent.SetShipping((float)10.5);
branchCommerceEvent.SetCurrency(BranchCurrencyType.USD);
branchCommerceEvent.SetTax((float)12.3);

Branch.GetInstance().SendEvent(branchCommerceEvent);

追踪 Content Event

  • Content Event 是用户与您的应用内内容互动时发生的事件。例如,如果您有应用内文章,则希望追踪与用户搜索,查看内容,对内容进行评级和分享有关的事件。这可以应用于多种应用内内容,例如博客文章,音乐,视频,图片和电子商务目录项。

  • Validate with the Branch Dashboard

BranchEvent branchContentEvent = new BranchEvent(BranchEventType.SEARCH);
branchContentEvent.SetAlias("my_custom_alias");
branchContentEvent.SetDescription("Product Search");
branchContentEvent.SetSearchQuery("user search query terms for product xyz");
branchContentEvent.AddCustomData("content_event_property_key1", "content_event_property_val1");

Branch.GetInstance().SendEvent(branchContentEvent);

追踪 Lifecycle Event

  • Lifecycle Event 事件可以描述为继续操作,用户在应用内产生的事件。当用户完成用户个人资料,注册或完成教程时,这些事件可以应用于游戏应用以及非游戏应用。

  • Validate with the Branch Dashboard

BranchEvent branchLifecycleEvent = new BranchEvent(BranchEventType.COMPLETE_REGISTRATION);
branchLifecycleEvent.SetAlias("registration_flow_xyz"); branchLifecycleEvent.SetDescription("Existing User Registration");
branchLifecycleEvent.AddCustomData("lifeycle_event_property_key1", "lifecycle_event_property_val1");

Branch.GetInstance().SendEvent(branchLifecycleEvent);

追踪自定义事件

  • 如果要追踪非预定义的事件,只需进行以下操作:

  • 强烈建议使用不超过40个字符,仅包含字母,数字,连字符,空格和下划线且不要以连字符开头的自定义事件名称。 Facebook 将不接受违反这些规则的事件,如果您启用 Facebook 集成,Branch 可能会清理您的事件名称以通过验证。

  • Validate with the Branch Dashboard

BranchEvent branchCustomEvent = new BranchEvent("custom_event");
 branchCustomEvent.SetAlias("custom_event_alias");
 branchCustomEvent.SetDescription("Custom Event Description");
 branchCustomEvent.AddCustomData("custom_event_property_key1", "custom_event_property_val1");
branchCustomEvent.AddCustomData("custom_event_property_key2", "custom_event_property_val2");

Branch.GetInstance().SendEvent(branchCustomEvent);

排查问题

测试深度链接 iOS

  • Create a deep link from the Branch Marketing Dashboard

  • 从设备中删除您的应用

  • 使用 Xcode 编译您的应用

  • 将深度链接粘贴到 Apple Notes

  • 长按深度链接(不是 3D Touch)

  • Click Open in "APP_NAME" to open your app (example)

无法将 Branch 所需的 NuGet 程序包添加到C#项目

如果未将项目配置为使用所需的 NuGet 程序包,则可能无法将其添加到C#项目中 PCL 4.5 - Profile78

  1. 右键点击项目名称,然后选择: Options
  2. 浏览菜单至 Build > General
  3. Current Profile更改为: PCL 4.5 - Profile78

更改 entitlement 后,将 iOS 应用部署到设备失败,并显示 Provisioning Profile 错误

Xamarin automatically populates the Bundle Identifier field in the Info.plist file with an all-lowercase value derived from the app's name. This value is in fact case sensitive and must match the value in the Apple Developer Portal precisely. The default Xamarin configuration may work when there are no entitlements configured and then suddenly begin failing after entitlements have been added.

This issue can be resolved by ensuring that the Bundle Identifier in the Info.plist matches the Bundle Identifier shown on the Apple Developer Portal.

  1. 打开Info.plist文件
  2. Enter the app's Bundle Identifier from the Apple Developer Portal in the Bundle Identifier field

示例应用

此存储库中包含四个功能齐全的演示应用:适用于 iOS 和 Android 平台的Xamarin Native 和 Xamarin Forms 应用。将这些应用用作集成 Branch SDK 的参考模型。

  • Testbed-Xamarin (Native apps)

  • Testbed-XamarinForms (Forms apps)


这个页面对您有帮助吗?