React Native

GitHub标签(最新日期)GitHub标签(最新日期)

❗️

iOS 11.2上通用链接行为不一致

将设备更新到iOS 11.2后,我们发现在安装应用程序后,该应用程序的AASA文件不再可靠地下载到您用户的设备上。因此,单击“通用”链接将不再始终打开该应用程序。您可以在分支链接上设置强制uri重定向模式,以使用URI方案打开应用程序。在Apple Bug报告中查看问题的详细信息。

❗️

Google Play 服务版本17+

如果您引用的是 Google Play 服务版本17或更高版本,则必须在此处完成 Google 的更新说明。

由于 Google Play 服务于2019年6月进行了重大更改,未完成更新步骤将导致 Branch 的 Android SDK(以及其他各种跨平台 SDK,例如 Unity)停止收集 Android AID,我们使用该 ID 来确保准确的深度链接和归因。

如果您运行的 Google Play 服务版本低于17,则无需更新。

配置 Branch

图片图片
图片图片

安装 Branch

选项1:Pure React本机应用程序

Expo注意:如果使用的是Expo,则必须首先从Expo退出应用程序,使用Expo Bare Workflow并按照以下说明进行操作。

expo eject

注意: react-native-branch需要react-native> = 0.60

  • 安装模块
yarn add [email protected]^5.0.0
npm install --save [email protected]^5.0.0
  • (可选)将branch.json文件添加到您应用的根目录(package.json旁边)。

您可以随时配置内容,但是在运行react-native link时内容必须存在,以便自动包含在本机项目中。这使您可以配置某些需要更改本机代码的行为。有关branch.json文件的完整详细信息,请参见https://rnbranch.app.link/branch-json

选项2:带有CocoaPods的本地iOS应用

  • 将这些行添加到您的 Podfile
pod 'react-native-branch', path: '../node_modules/react-native-branch'
  • 运行pod install以使用新的依赖项重新生成Pods项目。请注意, node_modules相对于您的Podfile可能有所不同。

  • (可选)将branch.json文件添加到您应用的根目录(package.json旁边)。请参阅https://rnbranch.app.link/branch-json

从早期版本更新或从v5.0.0开始

iOS

  • 在AppDelegate中,将[RNBranch.branch application:app openURL:url options:options]替换为[RNBranch application:app openURL:url options:options]RNBranch.branch => RNBranch ),例如
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RNBranch application:app openURL:url options:options];
}

安卓

  • MainActivity.onNewIntent ,将setIntent(intent)替换为RNBranchModule.onNewIntent(intent) ,例如
  @Override
  public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    RNBranchModule.onNewIntent(intent);
  }

配置应用

iOS

  • 配置捆绑包标识符

  • 配置关联的域

  • 配置权利

    • 确认权利在目标范围内

      图片图片

  • 配置 Info.plist

    • 添加 Branch 操作后台 (Dashboard)的值

      • branch_universal_link_domains 下添加您的 live key 下的域名
      • branch_universal_link_domains 下添加您当前使用的 Branch key
      • 添加您的URI Scheme为URL Types - > Item 0 - > URL Schemes

      图片图片

  • 确认应用程序前缀

安卓

  • AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.eneff.branchandroid">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:name="com.eneff.branchandroid.CustomApplicationClass"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTask"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- Branch URI Scheme -->
            <intent-filter>
                <data android:scheme="branchandroid" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>

            <!-- Branch App Links (optional) -->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="https" android:host="uobg.app.link" />
            </intent-filter>
        </activity>
      
        <!-- Branch keys -->
        <!-- (Omit if setting keys in branch.json) -->
        <meta-data android:name="io.branch.sdk.BranchKey" android:value="key_live_gdzsepIaUf7wG3dEWb3aBkmcutm0PwJa"/>
        <meta-data android:name="io.branch.sdk.BranchKey.test" android:value="key_test_edwDakKcMeWzJ3hC3aZs9kniyuaWGCTa"/>
      
    </application>

</manifest>
  • 将以下内容替换为分支仪表板中的

    • branchandroid
    • uobg.app.link
    • key_live_gdzsepIaUf7wG3dEWb3aBkmcutm0PwJa
    • key_test_edwDakKcMeWzJ3hC3aZs9kniyuaWGCTa
  • android/app/proguard-rules.pro
    -dontwarn io.branch.**

初始化 Branch

iOS

Objective-C

将`#import <RNBranch / RNBranch.h>添加到您的AppDelegate.m。

Swift

如果Podfile中有use_frameworks! ,则将import RNBRanch添加到AppDelegate.swift。

如果您的Podfile中没有use_frameworks! ,则将#import <RNBranch/RNBranch.h>添加到您的桥接头中。

import RNBranch
// import react_native_branch // with 3.x

// Initialize the Branch Session at the top of existing application:didFinishLaunchingWithOptions:
func application(_ application: UIApplication, didFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // Uncomment this line to use the test key instead of the live one.
  // RNBranch.useTestInstance()
  RNBranch.initSession(launchOptions: launchOptions, isReferrable: true) // <-- add this

  //...
}

// Add the openURL and continueUserActivity functions
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  return RNBranch.application(app, open:url, options:options)
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
  return RNBranch.continue(userActivity)
}
#import <RNBranch/RNBranch.h> // at the top
// #import <react-native-branch/RNBranch.h> // with 3.x

// Initialize the Branch Session at the top of existing application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Uncomment this line to use the test key instead of the live one.
    // [RNBranch useTestInstance];
    [RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES]; // <-- add this
    NSURL *jsCodeLocation;
    //...
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    if ([RNBranch application:app openURL:url options:options])  {
        // do other deep link routing for the Facebook SDK, Pinterest SDK, etc
    }
    return YES;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
    return [RNBranch continueUserActivity:userActivity];
}

安卓

  • MainApplication.java
// ...

// import from RNBranch
import io.branch.rnbranch.RNBranchModule;

//...

// add onCreate() override
@Override
public void onCreate() {
  super.onCreate();
  RNBranchModule.getAutoInstance(this);
}
// ...

// imports from RNBranch
import io.branch.rnbranch.RNBranchModule;
import io.branch.rnbranch.RNBranchPackage;

//...

// add RNBranchPackage to react-native package list
@Override
  protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new RNBranchPackage(), // <-- add this

// ...

// add onCreate() override
@Override
public void onCreate() {
  super.onCreate();
  RNBranchModule.getAutoInstance(this);
}
  • MainActivity.java
import io.branch.rnbranch.*; // <-- add this
import android.content.Intent; // <-- and this

public class MainActivity extends ReactActivity {

      @Override
      protected String getMainComponentName() {
          return "base";
      }

      // Override onStart, onNewIntent:
      @Override
      protected void onStart() {
          super.onStart();
          RNBranchModule.initSession(getIntent().getData(), this);
      }

      @Override
      public void onNewIntent(Intent intent) {
          super.onNewIntent(intent);
          RNBranchModule.onNewIntent(intent);
      }
      // ...
}

实施功能

进口分公司

  • 在任何使用Branch SDK的React Native源文件中。
import branch, { BranchEvent } from 'react-native-branch'

创建内容参考

  • 使用 Branch Universal Object 封装您要共享的内容(内容或用户)

  • 使用通用对象属性

// only canonicalIdentifier is required
let branchUniversalObject = await branch.createBranchUniversalObject('canonicalIdentifier', {
  locallyIndex: true,
  title: 'Cool Content!',
  contentDescription: 'Cool Content Description',
  contentMetadata: {
    ratingAverage: 4.2,
    customMetadata: {
      prop1: 'test',
      prop2: 'abc'
    }
  }
})

创建深度链接

  • 创建链接URL并封装数据

  • 需要一个分支通用对象

  • 使用深层链接属性

  • 使用 Branch 控制面板进行验证

let linkProperties = {
    feature: 'share',
    channel: 'facebook'
}

let controlParams = {
     $desktop_url: 'http://desktop-url.com/monster/12345'
}

let {url} = await branchUniversalObject.generateShortUrl(linkProperties, controlParams)

分享深度链接

  • 生成 Branch 深度链接,并通过用户选择的渠道(Channel)进行标记

  • 需要一个分支通用对象

  • 使用深层链接属性

let shareOptions = { messageHeader: 'Check this out', messageBody: 'No really, check this out!' }
let linkProperties = { feature: 'share', channel: 'RNApp' }
let controlParams = { $desktop_url: 'http://example.com/home', $ios_url: 'http://example.com/ios' }
let {channel, completed, error} = await branchUniversalObject.showShareSheet(shareOptions, linkProperties, controlParams)

读取深度链接

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

  • 最佳做法是从listener 接收数据(以防止出现race condition)

  • 返回深层链接属性

  • 听众

branch.subscribe(({error, params, uri}) => {
  if (error) {
    console.error('Error from Branch: ' + error)
    return
  }

  // params will never be null if error is null
})

let lastParams = await branch.getLatestReferringParams() // params from last open
let installParams = await branch.getFirstReferringParams() // params from original install

导航至内容

branch.subscribe(({error, params, uri}) => {
  if (error) {
    console.error('Error from Branch: ' + error)
    return
  }

  // params will never be null if error is null

  if (params['+non_branch_link']) {
    const nonBranchUrl = params['+non_branch_link']
    // Route non-Branch URL if appropriate.
    return
  }

  if (!params['+clicked_branch_link']) {
    // Indicates initialization success and some other conditions.
    // No link was opened.
    return
  }

  // A Branch link was opened.
  // Route link based on data in params, e.g.

  // Get title and url for route
  const title = params.$og_title
  const url = params.$canonical_url
  const image = params.$og_image_url

  // Now push the view for this URL
  this.navigator.push({ title: title, url: url, image: image })
})

调整缓存的链接TTL

  • 启动应用程序的任何链接均由本机层缓存,并在JavaScript完成加载后返回到branch.subscribe侦听器。

  • 默认情况下,初始链接被缓存5秒钟。这使您可以取消订阅并稍后重新订阅,而无需接收初始链接。

  • 如果您的应用加载时间超过此时间,则可以通过将branch.initSessionTtl调整为毫秒值来调整初始链接的TTL。

branch.initSessionTtl = 10000 // Set to 10 seconds
branch.subscribe({ error, params } => {
  // ...
})

展示内容

  • 在iOS Spotlight上列出内容

  • 需要一个分支通用对象

  • 在Spotlight上列出要求将CoreSpotlight.framework添加到您的Xcode项目中。

let branchUniversalObject = await branch.createBranchUniversalObject('canonicalIdentifier', {
  locallyIndex: true,
  // other properties
})

branchUniversalObject.logEvent(BranchEvent.ViewItem)

跟踪内容

  • 跟踪一段内容的查看次数

  • 需要一个分支通用对象

  • 使用跟踪内容属性

  • 使用 Branch 控制面板进行验证

import { BranchEvent } from 'react-native-branch'
branchUniversalObject.logEvent(BranchEvent.ViewItem)

跟踪用户

  • 设置事件、深度链接和推荐的用户标识(电子邮件、ID 和 UUID 等)

  • 使用 Branch 控制面板进行验证

branch.setIdentity('theUserId')
branch.logout()

径赛项目

  • 跟踪标准和自定义事件

  • 名为opencloseinstallreferred session受分支限制

  • 63 事件名称的最大长度

  • 最好在跟踪事件之前跟踪用户以将自定义事件与用户相关联

  • 使用 Branch 控制面板进行验证

import { BranchEvent } from 'react-native-branch'

// Associate one or more content items with an event
new BranchEvent(BranchEvent.ViewItems, [buo1, buo2]).logEvent()

// Log a standard event with parameters
new BranchEvent(BranchEvent.Purchase, buo, {
  revenue: 20,
  shipping: 2,
  tax: 1.6,
  currency: 'USD'
}).logEvent()

// Set parameters after initialization
let event = new BranchEvent(BranchEvent.Search)
event.searchQuery = "tennis rackets"
event.logEvent()

// Log a custom event
new BranchEvent("UserScannedItem", buo).logEvent()
  • 使用单个Branch Universal Object记录事件时,请使用方便的logEvent方法
buo.logEvent(BranchEvent.ViewItem)
buo.logEvent(BranchEvent.Purchase, { revenue: 20 })

标准活动

事件常数描述
BranchEvent.AddToCart标准添加到购物车事件
BranchEvent.AddToWishlist标准的“添加到收藏”活动
BranchEvent.ViewCart标准视图购物车事件
BranchEvent.InitiatePurchase标准发起购买活动
BranchEvent.AddPaymentInfo标准添加付款信息事件
BranchEvent.Purchase标准购买活动
BranchEvent.SpendCredits标准消费抵免额事件
BranchEvent.Search标准搜索活动
BranchEvent.ViewItem单个分支通用对象的标准视图项事件
BranchEvent.ViewItems多个分支通用对象的标准视图项事件
BranchEvent.Rate标准汇率事件
BranchEvent.Share标准股事件
BranchEvent.CompleteRegistration标准完整注册活动
BranchEvent.CompleteTutorial标准完整教程活动
BranchEvent.AchieveLevel标准达到水平事件
BranchEvent.AchievementUnlocked标准解锁成就事件

处理您自己的应用程序中的深度链接

  • 允许您从应用内深度链接到应用本身
branch.openURL("https://example.app.link/u3fzDwyyjF")
branch.openURL("https://example.app.link/u3fzDwyyjF", {newActivity: true}) // Finish the Android current activity before opening the link. Results in a new activity window. Ignored on iOS.

❗️

处理新的深层链接

在您的应用程序中处理新的深度链接接将清除当前会话数据,并将新引用的"设为" 。

处理推送通知

  • 允许您在推送通知中追踪 Branch 深度链接

  • 使用openURL处理深层链接

追踪 Apple Search Ads

  • 允许 Branch 追踪 Apple Search Ads 深度链接分析

  • Apple API 的分析数据生成速度很慢,会影响到我们的分析数据。此外,Apple 的API 不会每次都向我们发送广告的所有数据,这有时会导致我们追踪的广告只显示一般的 campaign。

  • 这需要在本地SDK初始化之前设置一个选项,
    发生在JS完成加载之前。有两种选择:

    1. "delayInitToCheckForSearchAds": true添加到您的branch.json文件中:
{
  "delayInitToCheckForSearchAds": true
}
  1. 在Xcode中修改您的AppDelegate。在对[RNBranch initSessionWithLaunchOptions:isReferrable:]的调用之前插入以下内容。
Branch.getInstance().delayInitToCheckForSearchAds()
[[Branch getInstance] delayInitToCheckForSearchAds];

启用100%匹配

安卓

  • 使用Chrome Tabs 增加属性匹配成功率

  • compile 'com.android.support:customtabs:28.0.0' 加到您的build.gradle

iOS

  • 使用SFSafariViewController提高归因匹配的成功率

  • 说100%匹配有些不妥,因为只有当用户在 Safari 浏览器点击时会有100%匹配。根据我们的分析,通过 Safari 浏览器点击的大约有50-75%,具体取决于用例。例如,从 Facebook 或 Chrome 浏览器点击不会触发100%的匹配。不过此技术仍然对匹配精度有利,所以我们建议采用它。

  • 使用自定义域时,在Info.plist中添加带有自定义域的branch_app_domain字符串键以启用100%匹配。

  • 默认情况下,如果应用程序的依赖项中包含SafariServices.framework ,并且该应用程序使用app.link子域或在Info.plist中设置branch_app_domain ,则在iOS 9和10上启用基于cookie的匹配。可以通过调用SDK来禁用它。

  • initSession Branch 初始化之前添加

Branch.getInstance().disableCookieBasedMatching()
[[Branch getInstance] disableCookieBasedMatching];

将元数据追加到分支网络呼叫

  • 用于附加元数据的函数,用于诸如插入用户ID以启用第三方数据集成之类的用例

iOS

RNBranch.setRequestMetadataKey("insert_user_id", "value")

安卓

RNBranchModule.setRequestMetadata("userID", "value");

在打开链接之前接收通知

需要react-native-branch 5.x

要通知Branch即将打开链接,请对branch.subscribe使用onOpenStart回调。还提供onOpenComplete回调,这与branch.subscribe通常使用的单个回调相同:

import branch from 'react-native-branch';

branch.subscribe({
  onOpenStart: ({uri, cachedInitialEvent}) => {
    // cachedInitialEvent is true if the event was received by the
    // native layer before JS loaded.
    console.log('Branch will open ' + uri);
  },
  onOpenComplete: ({error, params,uri}) => {
    if (error) {
      console.error('Error from Branch opening uri ' + uri);
      return;
    }

    console.log('Branch opened ' + uri);
    // handle params
  },
})

请注意,在某些情况下,uri将为null,特别是在延迟的深层链接的情况下。在这些情况下,请查阅〜referring_link,+ url或+ non_branch_link的参数以确定引用URI / URL。

解决问题

测试深层链接iOS

  • 分支营销仪表板创建深层链接

  • 从设备中删除您的应用程序

  • 使用Xcode编译您的应用

  • 粘贴深度链接到 Apple Notes

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

  • 点击Open in "APP_NAME"打开您的应用示例

测试深层链接Android

  • 分支营销仪表板创建深层链接

  • 从设备中删除您的应用程序

  • 使用Android Studio编译您的应用

  • 粘贴深度链接到 Google Hangouts

  • 点击深层链接打开您的应用

使用测试键

  • 使用分支test key代替live key

  • 在iOS中,在initSession Initialize Branch之前添加。

  • 在iOS中,将Info.plist中的branch_key更新为字典(例如)。

  • 在Android中,将test mode设置为true

  • 应用程序的test key必须与深层链接的test key相匹配。

  • 在发布到生产环境之前,请使用条件编译或删除。

#if DEBUG
RNBranch.useTestInstance()
#endif
#if DEBUG
  RNBranch.useTestInstance()
  #endif
  • Android:将其用于构建类型或产品风格,或确保在删除之前
    投入生产。
    <meta-data android:name="io.branch.sdk.TestMode" android:value="true" />

模拟安装

不要在生产中进行测试。

这要求必须在加载JS之前进行本机方法调用。有两种选择。

  1. 在项目中使用branch.json文件。有关完整详细信息,请参见https://rnbranch.app.link/branch-json
    "debugMode": true添加到branch.debug.json
{
  "appleSearchAdsDebugMode": true,
    "debugMode": true,
      "delayInitToCheckForSearchAds": true
}

不要将此设置添加到branch.json ,否则将为发布版本启用此设置。

  1. 修改您的本机应用代码。

安卓

可以通过在Android清单的application元素中添加<meta-data android:name="io.branch.sdk.TestMode" android:value="true"/>来在Android上启用模拟安装。在构建类型(例如debug或产品风味)中使用此命令,或者在发布到产品之前确保从清单中删除它。单击此处了解更多详细信息。

或者,在调用initSession之前的MainActivity中添加RNBranchModule.setDebug(); 。在发布到产品之前,请确保将其删除。

// Remove before prod release
RNBranchModule.setDebug();
RNBranchModule.initSession(getIntent().getData(), this);

iOS

在对initSession的调用之前,在AppDelegate中添加[RNBranch setDebug];RNBranch.setDebug()

在发布到产品之前,请使用条件编译或删除。

#if DEBUG
RNBranch.setDebug()
#endif
RNBranch.initSession(launchOptions: launchOptions, isReferrable: true)
#ifdef DEBUG
  [RNBranch setDebug];
#endif
  [RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES];

使用getLatestReferringParams处理链接打开

getLatestReferringParams方法本质上是一种同步方法,它检索由本机SDK存储的最新引用链接参数。但是,React Native不支持从JavaScript同步调用本机代码,因此该方法返回一个promise。您必须await响应或使用then来接收结果。相同的说明适用于getFirstReferringParams方法。

但是,这仅是React Native的限制。 getLatestReferringParams的用途是一次检索这些参数。承诺只会返回一个结果。当打开链接或等待链接打开时,它将不会继续返回结果。此方法并非旨在在链接打开时通知应用程序。

要在链接打开时(包括在应用启动时)接收通知,请致电
branch.subscribe 。此方法的回调将返回启动了
应用程序和所有后续链接打开。应用启动时无需调用getLatestReferringParams来检查初始链接。使用branch.subscribe处理所有链接打开。

常见的构建问题

  • Be sure to follow the instructions to Update from < 2.0.0 if your
    app used an earlier version of react-native-branch. In version 2.x, the native SDKs are embedded
    in the NPM module and must not also be added from elsewhere (Gradle, CocoaPods, etc.).

  • 请注意,在本机应用程序中使用React吊舱时,本机SDK吊舱的名称为Branch-SDK而不是Branch ,它来自node_modules而不是CocoaPods仓库。

  • 从React Native 0.40开始,必须将Objective-C中的所有外部iOS标头导入为
    #import <PackageName/Header.h> 。这适用于React Native标头以及此SDK中的<react-native-branch/RNBranch.h>标头。

  • 如果您是从RN <0.40手动升级的,而没有调整Xcode项目设置,则可能
    仍在导入带有双引号的标头。这可能表明您的设置有问题。

  • NPM的react-native-git-upgrade工具可用于更新依赖关系以及项目设置。

  • 在Android上,在发行版本中使用Proguard时,取决于您的构建设置,可能是
    必须将以下两行之一或全部添加到您的android/app/proguard-rules.pro文件中:

-dontwarn com.crashlytics.android.answers.shim.**
-dontwarn com.google.firebase.appindexing.**

常规故障排除

请参阅每个本机SDK的故障排除指南:

示例应用

2个月前更新


React Native


建议的编辑仅限于API参考页

您只能建议对Markdown正文内容进行修改,而不能建议对API规范进行修改。