0
# Gaming Services
1
2
The Facebook Gaming Services module provides gaming-specific features including tournaments, gaming contexts, friend finder, custom updates, and social gaming capabilities. This module is designed specifically for games that want to integrate with Facebook's gaming platform.
3
4
## Gaming Context
5
6
Manage gaming contexts for multiplayer and social gaming experiences:
7
8
```kotlin { .api }
9
class GamingContext private constructor() {
10
val identifier: String?
11
12
companion object {
13
// Current context
14
fun getCurrentGamingContext(): GamingContext?
15
16
// Context switching
17
fun switchGamingContext(
18
context: Context,
19
gamingContextId: String,
20
callback: FacebookCallback<GamingContext>
21
)
22
23
fun createGamingContext(
24
activity: Activity,
25
playerID: String,
26
callback: FacebookCallback<GamingContext>
27
)
28
}
29
}
30
```
31
32
### Gaming Context Usage
33
34
```kotlin
35
class MultiplayerGameActivity : AppCompatActivity() {
36
37
override fun onCreate(savedInstanceState: Bundle?) {
38
super.onCreate(savedInstanceState)
39
40
// Check current gaming context
41
val currentContext = GamingContext.getCurrentGamingContext()
42
if (currentContext != null) {
43
Log.d("Gaming", "Current context: ${currentContext.identifier}")
44
loadMultiplayerGame(currentContext.identifier)
45
} else {
46
// Create new gaming context or switch to existing one
47
createOrSwitchContext()
48
}
49
}
50
51
private fun createOrSwitchContext() {
52
// Option 1: Create new context with a friend
53
val friendPlayerId = "friend_user_id_123"
54
GamingContext.createGamingContext(this, friendPlayerId) { result ->
55
when {
56
result.error != null -> {
57
Log.e("Gaming", "Failed to create context: ${result.error?.message}")
58
}
59
result.cancelled -> {
60
Log.d("Gaming", "Context creation cancelled")
61
}
62
else -> {
63
val context = result.result
64
Log.d("Gaming", "Created context: ${context?.identifier}")
65
startMultiplayerGame(context)
66
}
67
}
68
}
69
70
// Option 2: Switch to existing context
71
val existingContextId = "existing_context_123"
72
GamingContext.switchGamingContext(this, existingContextId) { result ->
73
when {
74
result.error != null -> {
75
Log.e("Gaming", "Failed to switch context: ${result.error?.message}")
76
}
77
result.cancelled -> {
78
Log.d("Gaming", "Context switch cancelled")
79
}
80
else -> {
81
val context = result.result
82
Log.d("Gaming", "Switched to context: ${context?.identifier}")
83
joinExistingGame(context)
84
}
85
}
86
}
87
}
88
}
89
```
90
91
## Gaming Dialogs
92
93
### Context Choose Dialog
94
95
Allow players to select or create gaming contexts:
96
97
```kotlin { .api }
98
class ContextChooseDialog : FacebookDialogBase<ContextChooseContent, ContextChooseDialog.Result> {
99
constructor(activity: Activity)
100
constructor(fragment: Fragment)
101
102
companion object {
103
fun canShow(): Boolean
104
}
105
106
fun show(content: ContextChooseContent)
107
108
data class Result(val contextId: String)
109
}
110
111
class ContextChooseContent private constructor() {
112
val filters: List<Filter>?
113
val maxSize: Int?
114
val minSize: Int?
115
116
enum class Filter {
117
NEW_CONTEXT_ONLY, // Only allow creating new contexts
118
INCLUDE_EXISTING // Include existing contexts
119
}
120
121
class Builder {
122
fun setFilters(filters: List<Filter>): Builder
123
fun setMaxSize(maxSize: Int): Builder
124
fun setMinSize(minSize: Int): Builder
125
fun build(): ContextChooseContent
126
}
127
}
128
```
129
130
### Context Create Dialog
131
132
Create new gaming contexts:
133
134
```kotlin { .api }
135
class ContextCreateDialog : FacebookDialogBase<ContextCreateContent, ContextCreateDialog.Result> {
136
constructor(activity: Activity)
137
constructor(fragment: Fragment)
138
139
companion object {
140
fun canShow(): Boolean
141
}
142
143
fun show(content: ContextCreateContent)
144
145
data class Result(val contextId: String)
146
}
147
148
class ContextCreateContent private constructor() {
149
val playerID: String
150
val suggestedPlayers: List<String>?
151
152
class Builder(playerID: String) {
153
fun setSuggestedPlayers(suggestedPlayers: List<String>): Builder
154
fun build(): ContextCreateContent
155
}
156
}
157
```
158
159
### Gaming Dialog Usage
160
161
```kotlin
162
class GamingDialogManager {
163
private lateinit var callbackManager: CallbackManager
164
165
fun showContextChooser(activity: Activity) {
166
val content = ContextChooseContent.Builder()
167
.setFilters(listOf(ContextChooseContent.Filter.INCLUDE_EXISTING))
168
.setMaxSize(8) // Maximum 8 players
169
.setMinSize(2) // Minimum 2 players
170
.build()
171
172
val dialog = ContextChooseDialog(activity)
173
dialog.registerCallback(callbackManager, object : FacebookCallback<ContextChooseDialog.Result> {
174
override fun onSuccess(result: ContextChooseDialog.Result) {
175
Log.d("Gaming", "Context chosen: ${result.contextId}")
176
switchToContext(result.contextId)
177
}
178
179
override fun onCancel() {
180
Log.d("Gaming", "Context selection cancelled")
181
}
182
183
override fun onError(error: FacebookException) {
184
Log.e("Gaming", "Context selection error: ${error.message}")
185
}
186
})
187
188
if (ContextChooseDialog.canShow()) {
189
dialog.show(content)
190
}
191
}
192
193
fun showContextCreator(activity: Activity, playerID: String, friends: List<String>) {
194
val content = ContextCreateContent.Builder(playerID)
195
.setSuggestedPlayers(friends)
196
.build()
197
198
val dialog = ContextCreateDialog(activity)
199
dialog.registerCallback(callbackManager, object : FacebookCallback<ContextCreateDialog.Result> {
200
override fun onSuccess(result: ContextCreateDialog.Result) {
201
Log.d("Gaming", "Context created: ${result.contextId}")
202
startNewGame(result.contextId)
203
}
204
205
override fun onCancel() {
206
Log.d("Gaming", "Context creation cancelled")
207
}
208
209
override fun onError(error: FacebookException) {
210
Log.e("Gaming", "Context creation error: ${error.message}")
211
}
212
})
213
214
if (ContextCreateDialog.canShow()) {
215
dialog.show(content)
216
}
217
}
218
}
219
```
220
221
## Friend Finder Dialog
222
223
Help players discover and invite friends:
224
225
```kotlin { .api }
226
class FriendFinderDialog : FacebookDialogBase<Void, FriendFinderDialog.Result> {
227
constructor(activity: Activity)
228
constructor(fragment: Fragment)
229
230
companion object {
231
fun canShow(): Boolean
232
}
233
234
fun show()
235
236
data class Result(
237
val requestId: String,
238
val to: List<String>
239
)
240
}
241
```
242
243
### Friend Finder Usage
244
245
```kotlin
246
fun showFriendFinder(activity: Activity) {
247
val dialog = FriendFinderDialog(activity)
248
dialog.registerCallback(callbackManager, object : FacebookCallback<FriendFinderDialog.Result> {
249
override fun onSuccess(result: FriendFinderDialog.Result) {
250
Log.d("Gaming", "Friend finder success")
251
Log.d("Gaming", "Request ID: ${result.requestId}")
252
Log.d("Gaming", "Invited friends: ${result.to}")
253
254
// Track successful friend invitations
255
trackFriendInvitations(result.to.size)
256
}
257
258
override fun onCancel() {
259
Log.d("Gaming", "Friend finder cancelled")
260
}
261
262
override fun onError(error: FacebookException) {
263
Log.e("Gaming", "Friend finder error: ${error.message}")
264
}
265
})
266
267
if (FriendFinderDialog.canShow()) {
268
dialog.show()
269
}
270
}
271
```
272
273
## Custom Updates
274
275
Send custom updates to gaming contexts:
276
277
```kotlin { .api }
278
class CustomUpdate private constructor() {
279
companion object {
280
fun newCustomUpdateBuilder(): Builder
281
}
282
283
class Builder {
284
fun setText(text: String): Builder
285
fun setImage(image: Bitmap): Builder
286
fun setCTA(cta: String): Builder
287
fun setData(data: JSONObject): Builder
288
fun setStrategy(strategy: Strategy): Builder
289
fun setNotification(notification: String): Builder
290
fun build(): CustomUpdate
291
}
292
293
enum class Strategy {
294
IMMEDIATE, // Send immediately
295
LAST, // Replace last update
296
REPLACE_ALL // Replace all updates
297
}
298
}
299
300
class CustomUpdateContent private constructor() {
301
val customUpdate: CustomUpdate
302
val contextID: String?
303
304
class Builder(customUpdate: CustomUpdate) {
305
fun setContextID(contextID: String): Builder
306
fun build(): CustomUpdateContent
307
}
308
}
309
```
310
311
### Custom Update Usage
312
313
```kotlin
314
class GameUpdateManager {
315
316
fun sendGameUpdate(
317
activity: Activity,
318
message: String,
319
screenshot: Bitmap,
320
gameData: JSONObject
321
) {
322
val customUpdate = CustomUpdate.newCustomUpdateBuilder()
323
.setText(message)
324
.setImage(screenshot)
325
.setCTA("Join Game")
326
.setData(gameData)
327
.setStrategy(CustomUpdate.Strategy.LAST)
328
.setNotification("Your turn!")
329
.build()
330
331
val contextId = GamingContext.getCurrentGamingContext()?.identifier
332
if (contextId != null) {
333
val content = CustomUpdateContent.Builder(customUpdate)
334
.setContextID(contextId)
335
.build()
336
337
sendCustomUpdate(activity, content)
338
}
339
}
340
341
fun sendScoreUpdate(score: Int, level: Int, screenshot: Bitmap) {
342
val gameData = JSONObject().apply {
343
put("score", score)
344
put("level", level)
345
put("timestamp", System.currentTimeMillis())
346
put("game_version", BuildConfig.VERSION_NAME)
347
}
348
349
val message = "I just scored $score points on level $level! Can you beat it?"
350
351
val customUpdate = CustomUpdate.newCustomUpdateBuilder()
352
.setText(message)
353
.setImage(screenshot)
354
.setCTA("Play Now")
355
.setData(gameData)
356
.setStrategy(CustomUpdate.Strategy.IMMEDIATE)
357
.build()
358
359
val contextId = GamingContext.getCurrentGamingContext()?.identifier
360
if (contextId != null) {
361
val content = CustomUpdateContent.Builder(customUpdate)
362
.setContextID(contextId)
363
.build()
364
365
sendCustomUpdate(activity, content)
366
}
367
}
368
369
fun sendTurnNotification(playerName: String, gameState: JSONObject) {
370
val customUpdate = CustomUpdate.newCustomUpdateBuilder()
371
.setText("$playerName made their move!")
372
.setCTA("Your Turn")
373
.setData(gameState)
374
.setStrategy(CustomUpdate.Strategy.REPLACE_ALL)
375
.setNotification("It's your turn to play!")
376
.build()
377
378
val contextId = GamingContext.getCurrentGamingContext()?.identifier
379
if (contextId != null) {
380
val content = CustomUpdateContent.Builder(customUpdate)
381
.setContextID(contextId)
382
.build()
383
384
sendCustomUpdate(activity, content)
385
}
386
}
387
}
388
```
389
390
## Tournament Support
391
392
### Tournament Fetcher
393
394
Retrieve tournament information:
395
396
```kotlin { .api }
397
class TournamentFetcher {
398
companion object {
399
fun fetchTournaments(callback: FacebookCallback<List<Tournament>>)
400
fun fetchTournament(tournamentId: String, callback: FacebookCallback<Tournament>)
401
}
402
}
403
404
data class Tournament(
405
val identifier: String,
406
val endTime: String,
407
val title: String?,
408
val payload: JSONObject?
409
)
410
```
411
412
### Tournament Share Dialog
413
414
Share tournament results and invite players:
415
416
```kotlin { .api }
417
class TournamentShareDialog : FacebookDialogBase<TournamentConfig, TournamentShareDialog.Result> {
418
constructor(activity: Activity)
419
constructor(fragment: Fragment)
420
421
companion object {
422
fun canShow(): Boolean
423
}
424
425
fun show(config: TournamentConfig)
426
427
data class Result(val tournamentId: String?)
428
}
429
430
class TournamentConfig private constructor() {
431
val title: String?
432
val endTime: String?
433
val scoreType: ScoreType?
434
val sortOrder: SortOrder?
435
val image: Bitmap?
436
val payload: JSONObject?
437
438
enum class ScoreType {
439
NUMERIC, // Numeric scores
440
TIME // Time-based scores
441
}
442
443
enum class SortOrder {
444
HIGHER_IS_BETTER, // Higher scores are better
445
LOWER_IS_BETTER // Lower scores are better (e.g., time)
446
}
447
448
class Builder {
449
fun setTitle(title: String): Builder
450
fun setEndTime(endTime: String): Builder
451
fun setScoreType(scoreType: ScoreType): Builder
452
fun setSortOrder(sortOrder: SortOrder): Builder
453
fun setImage(image: Bitmap): Builder
454
fun setPayload(payload: JSONObject): Builder
455
fun build(): TournamentConfig
456
}
457
}
458
```
459
460
### Tournament Usage
461
462
```kotlin
463
class TournamentManager {
464
465
fun createTournament(
466
activity: Activity,
467
title: String,
468
duration: Long,
469
screenshot: Bitmap
470
) {
471
val endTime = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
472
timeZone = TimeZone.getTimeZone("UTC")
473
}.format(Date(System.currentTimeMillis() + duration))
474
475
val payload = JSONObject().apply {
476
put("game_mode", "tournament")
477
put("created_by", AccessToken.getCurrentAccessToken()?.userId)
478
put("created_at", System.currentTimeMillis())
479
}
480
481
val config = TournamentConfig.Builder()
482
.setTitle(title)
483
.setEndTime(endTime)
484
.setScoreType(TournamentConfig.ScoreType.NUMERIC)
485
.setSortOrder(TournamentConfig.SortOrder.HIGHER_IS_BETTER)
486
.setImage(screenshot)
487
.setPayload(payload)
488
.build()
489
490
val dialog = TournamentShareDialog(activity)
491
dialog.registerCallback(callbackManager, object : FacebookCallback<TournamentShareDialog.Result> {
492
override fun onSuccess(result: TournamentShareDialog.Result) {
493
val tournamentId = result.tournamentId
494
Log.d("Tournament", "Tournament created: $tournamentId")
495
startTournamentGame(tournamentId)
496
}
497
498
override fun onCancel() {
499
Log.d("Tournament", "Tournament creation cancelled")
500
}
501
502
override fun onError(error: FacebookException) {
503
Log.e("Tournament", "Tournament creation error: ${error.message}")
504
}
505
})
506
507
if (TournamentShareDialog.canShow()) {
508
dialog.show(config)
509
}
510
}
511
512
fun fetchActiveTournaments() {
513
TournamentFetcher.fetchTournaments(object : FacebookCallback<List<Tournament>> {
514
override fun onSuccess(result: List<Tournament>) {
515
Log.d("Tournament", "Found ${result.size} tournaments")
516
result.forEach { tournament ->
517
Log.d("Tournament", "Tournament: ${tournament.title} (${tournament.identifier})")
518
Log.d("Tournament", "Ends: ${tournament.endTime}")
519
}
520
displayTournaments(result)
521
}
522
523
override fun onCancel() {
524
Log.d("Tournament", "Tournament fetch cancelled")
525
}
526
527
override fun onError(error: FacebookException) {
528
Log.e("Tournament", "Tournament fetch error: ${error.message}")
529
}
530
})
531
}
532
533
fun submitTournamentScore(tournamentId: String, score: Int) {
534
// Tournament scores are typically submitted through Game Events
535
val logger = AppEventsLogger.newLogger(context)
536
val parameters = Bundle().apply {
537
putString("tournament_id", tournamentId)
538
putInt("score", score)
539
putLong("timestamp", System.currentTimeMillis())
540
}
541
logger.logEvent("tournament_score_submitted", score.toDouble(), parameters)
542
}
543
}
544
```
545
546
## Gaming Group Integration
547
548
Integration with Facebook Gaming Groups:
549
550
```kotlin { .api }
551
class GamingGroupIntegration {
552
companion object {
553
fun openGroupCreationDialog(
554
activity: Activity,
555
name: String,
556
description: String,
557
privacy: GroupPrivacy
558
)
559
560
fun openGameGroupTab(activity: Activity)
561
562
fun performAppToUserFriendFinderDialog(
563
activity: Activity,
564
callback: FacebookCallback<FriendFinderDialog.Result>
565
)
566
}
567
568
enum class GroupPrivacy {
569
PRIVATE,
570
PUBLIC
571
}
572
}
573
```
574
575
## Gaming Analytics
576
577
Track gaming-specific events and metrics:
578
579
```kotlin
580
class GamingAnalytics {
581
private val logger = AppEventsLogger.newLogger(context)
582
583
fun trackGameStart(gameMode: String, level: Int) {
584
val parameters = Bundle().apply {
585
putString("game_mode", gameMode)
586
putInt("level", level)
587
putLong("session_start", System.currentTimeMillis())
588
}
589
logger.logEvent("game_started", parameters)
590
}
591
592
fun trackGameEnd(gameMode: String, score: Int, duration: Long) {
593
val parameters = Bundle().apply {
594
putString("game_mode", gameMode)
595
putInt("final_score", score)
596
putLong("game_duration", duration)
597
putLong("session_end", System.currentTimeMillis())
598
}
599
logger.logEvent("game_ended", score.toDouble(), parameters)
600
}
601
602
fun trackMultiplayerAction(action: String, contextId: String?) {
603
val parameters = Bundle().apply {
604
putString("multiplayer_action", action)
605
contextId?.let { putString("context_id", it) }
606
putLong("action_timestamp", System.currentTimeMillis())
607
}
608
logger.logEvent("multiplayer_action", parameters)
609
}
610
611
fun trackTournamentParticipation(tournamentId: String, action: String) {
612
val parameters = Bundle().apply {
613
putString("tournament_id", tournamentId)
614
putString("tournament_action", action) // "joined", "score_submitted", "completed"
615
putLong("action_timestamp", System.currentTimeMillis())
616
}
617
logger.logEvent("tournament_participation", parameters)
618
}
619
620
fun trackSocialFeatureUsage(feature: String, success: Boolean) {
621
val parameters = Bundle().apply {
622
putString("social_feature", feature) // "friend_invite", "context_switch", "custom_update"
623
putBoolean("success", success)
624
putLong("usage_timestamp", System.currentTimeMillis())
625
}
626
logger.logEvent("social_feature_used", parameters)
627
}
628
}
629
```