or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-events.mdapp-links.mdbolts-tasks.mdcore-authentication.mdgaming.mdgraph-api.mdindex.mdlogin.mdmessenger.mdsharing.md

app-links.mddocs/

0

# App Links

1

2

Facebook App Links provide deep linking functionality for seamless navigation between apps and handling of Facebook App Links. This enables users to navigate directly from Facebook content to specific screens within your app.

3

4

## App Link Data

5

6

Extract and handle App Link data from incoming intents:

7

8

```kotlin { .api }

9

class AppLinkData private constructor() {

10

val targetUri: Uri?

11

val ref: String?

12

val extras: Bundle?

13

val argumentBundle: Bundle?

14

val promotionCode: String?

15

16

companion object {

17

// Extract from activity

18

fun createFromActivity(activity: Activity): AppLinkData?

19

fun createFromAlBundle(appLinkBundle: Bundle): AppLinkData?

20

21

// Deferred deep linking

22

fun fetchDeferredAppLinkData(

23

context: Context,

24

callback: CompletionHandler

25

)

26

27

// Deferred deep linking with specific app link ID

28

fun fetchDeferredAppLinkData(

29

context: Context,

30

applicationId: String?,

31

callback: CompletionHandler

32

)

33

}

34

35

interface CompletionHandler {

36

fun onDeferredAppLinkDataFetched(appLinkData: AppLinkData?)

37

}

38

}

39

```

40

41

### Basic App Links Usage

42

43

```kotlin

44

class MainActivity : AppCompatActivity() {

45

override fun onCreate(savedInstanceState: Bundle?) {

46

super.onCreate(savedInstanceState)

47

48

// Handle direct app links

49

handleAppLink()

50

51

// Handle deferred app links (for new installs)

52

handleDeferredAppLink()

53

}

54

55

private fun handleAppLink() {

56

val appLinkData = AppLinkData.createFromActivity(this)

57

if (appLinkData != null) {

58

val targetUri = appLinkData.targetUri

59

val ref = appLinkData.ref

60

val extras = appLinkData.extras

61

val promotionCode = appLinkData.promotionCode

62

63

Log.d("AppLinks", "App link received:")

64

Log.d("AppLinks", "Target URI: $targetUri")

65

Log.d("AppLinks", "Ref: $ref")

66

Log.d("AppLinks", "Promotion Code: $promotionCode")

67

68

// Navigate to specific content based on app link

69

navigateToContent(targetUri, extras)

70

}

71

}

72

73

private fun handleDeferredAppLink() {

74

AppLinkData.fetchDeferredAppLinkData(this) { appLinkData ->

75

if (appLinkData != null) {

76

Log.d("AppLinks", "Deferred app link data received")

77

val targetUri = appLinkData.targetUri

78

val ref = appLinkData.ref

79

80

// Handle deferred deep link (e.g., after app install)

81

navigateToContent(targetUri, appLinkData.extras)

82

} else {

83

Log.d("AppLinks", "No deferred app link data")

84

}

85

}

86

}

87

88

private fun navigateToContent(uri: Uri?, extras: Bundle?) {

89

if (uri != null) {

90

when (uri.path) {

91

"/product" -> {

92

val productId = uri.getQueryParameter("id")

93

openProductDetail(productId)

94

}

95

"/article" -> {

96

val articleId = uri.getQueryParameter("id")

97

openArticle(articleId)

98

}

99

"/promotion" -> {

100

val promotionCode = extras?.getString("promotion_code")

101

applyPromotion(promotionCode)

102

}

103

else -> {

104

// Default navigation

105

Log.d("AppLinks", "Unknown app link path: ${uri.path}")

106

}

107

}

108

}

109

}

110

}

111

```

112

113

## App Links Utilities

114

115

Utility functions for working with App Links:

116

117

```kotlin { .api }

118

class AppLinks {

119

companion object {

120

// Check if app link data exists in intent

121

fun getAppLinkData(intent: Intent): AppLinkData?

122

123

// Get target URL from app link data

124

fun getTargetUrl(appLinkData: AppLinkData): String?

125

126

// Get target URL from intent

127

fun getTargetUrlFromIncomingIntent(context: Context, intent: Intent): String?

128

}

129

}

130

```

131

132

## Facebook App Link Resolver

133

134

Resolve App Links using Facebook's resolution service:

135

136

```kotlin { .api }

137

class FacebookAppLinkResolver : AppLinkResolver {

138

constructor()

139

constructor(userAgent: String?)

140

141

override fun getAppLinkFromUrlInBackground(url: Uri): Task<AppLink>

142

override fun getAppLinksFromUrlsInBackground(urls: List<Uri>): Task<Map<Uri, AppLink>>

143

144

companion object {

145

fun getWebFallbackUrl(url: Uri, userAgent: String?): Task<Uri>

146

}

147

}

148

```

149

150

### App Link Resolution Example

151

152

```kotlin

153

// Using Bolts Tasks framework

154

fun resolveAppLinks(urls: List<Uri>) {

155

val resolver = FacebookAppLinkResolver()

156

157

resolver.getAppLinksFromUrlsInBackground(urls)

158

.continueWith { task ->

159

if (task.isFaulted) {

160

Log.e("AppLinks", "Error resolving app links: ${task.error}")

161

return@continueWith null

162

}

163

164

val appLinks = task.result

165

appLinks?.forEach { (url, appLink) ->

166

Log.d("AppLinks", "URL: $url")

167

Log.d("AppLinks", "App Link: ${appLink.sourceUrl}")

168

169

// Check available targets

170

appLink.targets.forEach { target ->

171

Log.d("AppLinks", "Target: ${target.url}")

172

Log.d("AppLinks", "Package: ${target.packageName}")

173

}

174

175

// Get web fallback URL

176

val webUrl = appLink.webUrl

177

Log.d("AppLinks", "Web fallback: $webUrl")

178

}

179

180

null

181

}

182

}

183

```

184

185

## Bolts App Links Integration

186

187

The App Links functionality integrates with the Bolts framework for App Link data models:

188

189

```kotlin { .api }

190

// From facebook-bolts module

191

class AppLink {

192

val sourceUrl: Uri

193

val targets: List<Target>

194

val webUrl: Uri?

195

196

data class Target(

197

val url: Uri?,

198

val appStoreId: String?,

199

val packageName: String?,

200

val className: String?

201

)

202

}

203

204

interface AppLinkResolver {

205

fun getAppLinkFromUrlInBackground(url: Uri): Task<AppLink>

206

fun getAppLinksFromUrlsInBackground(urls: List<Uri>): Task<Map<Uri, AppLink>>

207

}

208

```

209

210

## Deep Link Navigation Patterns

211

212

Common patterns for handling different types of deep links:

213

214

```kotlin

215

class DeepLinkHandler {

216

fun handleAppLink(activity: Activity) {

217

val appLinkData = AppLinkData.createFromActivity(activity)

218

if (appLinkData != null) {

219

val targetUri = appLinkData.targetUri

220

val ref = appLinkData.ref

221

222

// Track app link usage for analytics

223

logAppLinkEvent(ref, targetUri.toString())

224

225

// Route based on URI structure

226

routeToDestination(activity, targetUri, appLinkData.extras)

227

}

228

}

229

230

private fun routeToDestination(activity: Activity, uri: Uri?, extras: Bundle?) {

231

when {

232

uri?.host == "product" -> {

233

val intent = Intent(activity, ProductDetailActivity::class.java)

234

intent.putExtra("product_id", uri.getQueryParameter("id"))

235

extras?.let { intent.putExtras(it) }

236

activity.startActivity(intent)

237

}

238

239

uri?.host == "user" -> {

240

val intent = Intent(activity, UserProfileActivity::class.java)

241

intent.putExtra("user_id", uri.getQueryParameter("id"))

242

activity.startActivity(intent)

243

}

244

245

uri?.host == "share" -> {

246

val contentId = uri.getQueryParameter("content_id")

247

val contentType = uri.getQueryParameter("type")

248

handleSharedContent(activity, contentId, contentType)

249

}

250

251

else -> {

252

// Default fallback

253

Log.w("AppLinks", "Unknown app link format: $uri")

254

activity.startActivity(Intent(activity, MainActivity::class.java))

255

}

256

}

257

}

258

259

private fun logAppLinkEvent(ref: String?, targetUrl: String) {

260

val logger = AppEventsLogger.newLogger(context)

261

val parameters = Bundle().apply {

262

putString("app_link_ref", ref)

263

putString("target_url", targetUrl)

264

putLong("timestamp", System.currentTimeMillis())

265

}

266

logger.logEvent("app_link_opened", parameters)

267

}

268

269

private fun handleSharedContent(activity: Activity, contentId: String?, contentType: String?) {

270

if (contentId != null && contentType != null) {

271

when (contentType) {

272

"article" -> openArticle(activity, contentId)

273

"video" -> openVideo(activity, contentId)

274

"product" -> openProduct(activity, contentId)

275

else -> Log.w("AppLinks", "Unknown content type: $contentType")

276

}

277

}

278

}

279

}

280

```

281

282

## Deferred Deep Linking

283

284

Handle users who install your app from a Facebook link:

285

286

```kotlin

287

class DeferredLinkHandler {

288

fun setupDeferredLinking(context: Context) {

289

// Fetch deferred app link data on app launch

290

AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->

291

if (appLinkData != null) {

292

// User came from a Facebook link before installing

293

handleDeferredLink(context, appLinkData)

294

295

// Track deferred conversion

296

trackDeferredConversion(appLinkData)

297

}

298

}

299

}

300

301

private fun handleDeferredLink(context: Context, appLinkData: AppLinkData) {

302

val targetUri = appLinkData.targetUri

303

val ref = appLinkData.ref

304

val promotionCode = appLinkData.promotionCode

305

306

Log.d("DeferredLinks", "Deferred app link data:")

307

Log.d("DeferredLinks", "Target: $targetUri")

308

Log.d("DeferredLinks", "Ref: $ref")

309

Log.d("DeferredLinks", "Promotion: $promotionCode")

310

311

// Save deferred link data for later use

312

val prefs = context.getSharedPreferences("deferred_links", Context.MODE_PRIVATE)

313

prefs.edit().apply {

314

putString("deferred_target_uri", targetUri?.toString())

315

putString("deferred_ref", ref)

316

putString("deferred_promotion", promotionCode)

317

putBoolean("has_deferred_link", true)

318

apply()

319

}

320

321

// Apply promotion code if available

322

if (promotionCode != null) {

323

applyWelcomePromotion(promotionCode)

324

}

325

326

// Show welcome flow or navigate to specific content

327

showDeferredLinkWelcome(context, targetUri)

328

}

329

330

private fun trackDeferredConversion(appLinkData: AppLinkData) {

331

val logger = AppEventsLogger.newLogger(context)

332

val parameters = Bundle().apply {

333

putString("deferred_link_ref", appLinkData.ref)

334

putString("deferred_target", appLinkData.targetUri?.toString())

335

putString("promotion_code", appLinkData.promotionCode)

336

}

337

logger.logEvent("deferred_app_link_conversion", parameters)

338

}

339

340

fun consumeDeferredLink(context: Context): AppLinkData? {

341

val prefs = context.getSharedPreferences("deferred_links", Context.MODE_PRIVATE)

342

if (prefs.getBoolean("has_deferred_link", false)) {

343

val targetUri = prefs.getString("deferred_target_uri", null)?.let { Uri.parse(it) }

344

val ref = prefs.getString("deferred_ref", null)

345

val promotion = prefs.getString("deferred_promotion", null)

346

347

// Clear the deferred link data

348

prefs.edit().clear().apply()

349

350

// Create synthetic AppLinkData

351

return if (targetUri != null) {

352

// Note: This is a simplified approach

353

// In reality, you'd need to construct the AppLinkData properly

354

createSyntheticAppLinkData(targetUri, ref, promotion)

355

} else null

356

}

357

return null

358

}

359

}

360

```

361

362

## Testing App Links

363

364

Test your App Links implementation:

365

366

```kotlin

367

class AppLinkTester {

368

fun testAppLinkHandling(activity: Activity) {

369

// Create test app link data

370

val testUri = Uri.parse("https://example.com/product?id=123&ref=facebook")

371

val testExtras = Bundle().apply {

372

putString("promotion_code", "WELCOME10")

373

putString("campaign", "summer_sale")

374

}

375

376

// Simulate app link intent

377

val testIntent = Intent(Intent.ACTION_VIEW, testUri).apply {

378

putExtras(testExtras)

379

}

380

381

// Test app link extraction

382

val appLinkData = AppLinkData.createFromActivity(activity)

383

if (appLinkData != null) {

384

Log.d("Test", "App link test successful")

385

Log.d("Test", "Target: ${appLinkData.targetUri}")

386

Log.d("Test", "Ref: ${appLinkData.ref}")

387

} else {

388

Log.w("Test", "No app link data found")

389

}

390

}

391

392

fun testDeferredLinks(context: Context) {

393

// Force fetch deferred app link for testing

394

AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->

395

if (appLinkData != null) {

396

Log.d("Test", "Deferred link test successful")

397

Log.d("Test", "Deferred target: ${appLinkData.targetUri}")

398

} else {

399

Log.d("Test", "No deferred app link data")

400

}

401

}

402

}

403

}

404

```

405

406

## Integration with Facebook Ads

407

408

App Links work seamlessly with Facebook advertising:

409

410

```kotlin

411

// Track app install attribution from Facebook ads

412

class FacebookAdTracker {

413

fun trackInstallAttribution(context: Context) {

414

AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->

415

if (appLinkData != null) {

416

val ref = appLinkData.ref

417

418

// Track attribution based on ref parameter

419

when {

420

ref?.startsWith("ad_") == true -> {

421

// User came from Facebook ad

422

trackAdConversion(ref, appLinkData)

423

}

424

ref?.startsWith("post_") == true -> {

425

// User came from Facebook post

426

trackPostConversion(ref, appLinkData)

427

}

428

ref?.startsWith("page_") == true -> {

429

// User came from Facebook page

430

trackPageConversion(ref, appLinkData)

431

}

432

}

433

}

434

}

435

}

436

437

private fun trackAdConversion(ref: String, appLinkData: AppLinkData) {

438

val logger = AppEventsLogger.newLogger(context)

439

val parameters = Bundle().apply {

440

putString("fb_ad_ref", ref)

441

putString("target_url", appLinkData.targetUri?.toString())

442

putString("promotion_code", appLinkData.promotionCode)

443

}

444

logger.logEvent("fb_ad_install_conversion", parameters)

445

}

446

}

447

```