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
-
配置捆绑包标识符
-
捆绑ID匹配分支仪表板
-
-
配置关联的域
-
从 Branch 操作后台 (Dashboard)添加链接域
-
-alternate
与网站内部的 Web Basic Integration 进行通用链接时需要使用。 -
test-
如果需要使用测试键,则需要 -
如果您使用自定义链接域 ,则需要包括旧链接域,
-alternate
链接域和新链接域
-
-
配置权利
-
确认权利在目标范围内
-
-
配置 Info.plist
-
- 在
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()
径赛项目
-
跟踪标准和自定义事件
-
名为
open
,close
,install
和referred 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完成加载之前。有两种选择:- 将
"delayInitToCheckForSearchAds": true
添加到您的branch.json
文件中:
- 将
{
"delayInitToCheckForSearchAds": true
}
- 在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之前进行本机方法调用。有两种选择。
- 在项目中使用
branch.json
文件。有关完整详细信息,请参见https://rnbranch.app.link/branch-json 。
将"debugMode": true
添加到branch.debug.json
:
{
"appleSearchAdsDebugMode": true,
"debugMode": true,
"delayInitToCheckForSearchAds": true
}
不要将此设置添加到branch.json
,否则将为发布版本启用此设置。
- 修改您的本机应用代码。
安卓
可以通过在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个月前更新