React Native

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和归因。

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

配置 Branch

图像
图像

安装 Branch

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

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

expo eject

React Native 0.60注意: 如果您使用的是React Native 0.60或更高版本,请使用版本5.x。如果您使用的是0.60之前的React Native版本,请使用3.x版本react-native-branch

  • 安装模块

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

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

  • 如果对RN < 0.60使用react-native-branch 3.x版本,则需要手动链接库:
react-native link react-native-branch

选项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

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

要解决Android长期存在的构建问题,必须从版本3.0.0开始,从Maven而不是从react-native-branch
模块中获取
本机Branch Android SDK。

在您的项目中打开android/app/build.gradle 文件。

删除此行:

implementation fileTree(dir: 'libs', include: ['*.jar'])

添加此行:

implementation "io.branch.sdk.android:library:3.0.4"

结果应该是这样的:

dependencies {
    implementation project(':react-native-branch')
    implementation "io.branch.sdk.android:library:3.0.4"
    implementation "com.android.support:appcompat-v7:23.0.1"
    implementation "com.facebook.react:react-native:+"  // From node_modules
}

如果您'重新使用旧版本的Gradle,则可能需要compile 而不是
implementation

建议将Application.onCreate
方法中的Branch.getAutoInstance 替换为RNBranchModule.getAutoInstance 。为了在branch.json 文件中设置Branch
键,这是必需的。

@Override
public void onCreate() {
  super.onCreate();
  SoLoader.init(this, /* native exopackage */ false);
  // Replace Branch.getAutoInstance(this); with:
  RNBranchModule.getAutoInstance(this);
}

配置应用

iOS

  • 配置 Bundle identifier

  • 配置associated domains(关联域)

  • 配置 entitlements

    • 确认权利在目标范围内

      图像

  • 配置 Info.plist

    • 添加 Branch 控制面板的参数

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

        图像

  • 确认应用程序前缀(app prefix)

安卓

  • 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>
  • 将以下内容替换为Branch仪表板

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

初始化 Branch

iOS

如果您使用的是Swift,并且Podfile中没有use_frameworks! ,则将#import <RNBranch/RNBranch.h> (4.x)或#import <react-native-branch/RNBranch.h> (3.x)添加到Bridging头中。

如果在本机应用程序中将React 容器与use_frameworks! ,则可以在AppDelegate.swift中简单地使用Swift导入: import RNBranch (4.x)或import react_native_branch (3.x)。

如果您的AppDelegate是用Objective-C编写的,请使用#import <RNBranch/RNBranch.h> (4.x)或#import <react-native-branch/RNBranch.h> (3.x)。

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);
          setIntent(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 调整{1} 以毫秒为单位的值来调整初始链接的TTL。

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

展示内容

  • 列出iOS Spotlight上的内容

  • 需要一个分支通用对象

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

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()

跟踪事件

  • 跟踪标准和自定义事件

  • 这些事件命名opencloseinstall ,和referred session 都是Branch预留的

  • 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 单个Branch通用对象的标准视图项事件
BranchEvent.ViewItems 多个Branch通用对象的标准视图项事件
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.

onResume方法而不是onStart方法

如果使用newActivity 选项不是' t,则必须将调用从RNBranch.initSession method 移到主活动' s onResume 方法而不是onStart

处理新的深层链接"

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

处理推送通知

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

  • 使用openURL处理深层链接

追踪Apple搜索广告

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

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

  • 这需要在本机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];

将元数据追加到Branch网络呼叫

  • 附加元数据的功能,用于诸如插入用户ID来启用第三方数据集成

iOS

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

安卓

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

在打开链接之前接收通知

需要react-native-branch 5.x

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

import branch from 'react-native-branch'

branch.subscribe({
  onOpenStart: ({uri}) => {
    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

  • Branch营销仪表板创建深度链接接

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

  • 使用Xcode编译您的应用

  • 粘贴深度链接到 Apple Notes

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

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

测试深度链接 Android

  • Branch营销仪表板创建深度链接接

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

  • 使用Android Studio编译您的应用

  • 粘贴深度链接到 Google Hangouts

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

使用test key

  • 使用Branch 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": truebranch.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 处理所有链接打开。

常见的构建问题

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

常规故障排除

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

示例应用

更新29 天前

React Native


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

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