0
# Graph API
1
2
The Facebook Graph API module provides direct access to Facebook's Graph API for reading and writing Facebook data. It offers request building, batch operations, response handling, and comprehensive error management.
3
4
## Graph Request
5
6
The GraphRequest class is the primary interface for making Graph API calls.
7
8
```kotlin { .api }
9
class GraphRequest private constructor() {
10
val accessToken: AccessToken?
11
val graphPath: String?
12
val httpMethod: HttpMethod
13
val parameters: Bundle?
14
val graphObject: JSONObject?
15
val tag: Any?
16
val version: String?
17
val skippedResultKeys: Set<String>?
18
val callback: Callback?
19
20
companion object {
21
// Me requests
22
fun newMeRequest(
23
accessToken: AccessToken?,
24
callback: GraphJSONObjectCallback?
25
): GraphRequest
26
27
fun newMyFriendsRequest(
28
accessToken: AccessToken?,
29
callback: GraphJSONArrayCallback?
30
): GraphRequest
31
32
// Generic requests
33
fun newGraphPathRequest(
34
accessToken: AccessToken?,
35
graphPath: String?,
36
callback: Callback?
37
): GraphRequest
38
39
// Post requests
40
fun newPostRequest(
41
accessToken: AccessToken?,
42
graphPath: String?,
43
graphObject: JSONObject?,
44
callback: Callback?
45
): GraphRequest
46
47
// Delete requests
48
fun newDeleteObjectRequest(
49
accessToken: AccessToken?,
50
objectId: String?,
51
callback: Callback?
52
): GraphRequest
53
54
// Places search
55
fun newPlacesSearchRequest(
56
accessToken: AccessToken?,
57
location: Location,
58
radiusInMeters: Int,
59
resultsLimit: Int,
60
searchText: String?,
61
callback: GraphJSONArrayCallback?
62
): GraphRequest
63
64
// Custom audience
65
fun newCustomAudienceThirdPartyIdRequest(
66
accessToken: AccessToken?,
67
context: Context,
68
callback: Callback?
69
): GraphRequest
70
}
71
72
// Execution
73
fun executeAsync(): GraphRequestAsyncTask
74
fun executeAndWait(): GraphResponse
75
76
// Configuration
77
fun setParameters(parameters: Bundle?)
78
fun setGraphObject(graphObject: JSONObject?)
79
fun setTag(tag: Any?)
80
fun setVersion(version: String?)
81
fun setSkippedResultKeys(skippedResultKeys: Collection<String>?)
82
fun setCallback(callback: Callback?)
83
84
// Callbacks
85
interface Callback {
86
fun onCompleted(response: GraphResponse)
87
}
88
89
interface GraphJSONObjectCallback {
90
fun onCompleted(jsonObject: JSONObject?, response: GraphResponse)
91
}
92
93
interface GraphJSONArrayCallback {
94
fun onCompleted(jsonArray: JSONArray?, response: GraphResponse)
95
}
96
97
interface OnProgressCallback {
98
fun onProgress(current: Long, max: Long)
99
}
100
}
101
102
enum class HttpMethod {
103
GET, POST, DELETE
104
}
105
```
106
107
### Basic Graph API Usage
108
109
```kotlin
110
// Get current user information
111
val request = GraphRequest.newMeRequest(
112
AccessToken.getCurrentAccessToken()
113
) { jsonObject, response ->
114
if (response.error == null) {
115
val userId = jsonObject?.getString("id")
116
val name = jsonObject?.getString("name")
117
val email = jsonObject?.getString("email")
118
119
Log.d("GraphAPI", "User: $name ($userId), Email: $email")
120
} else {
121
Log.e("GraphAPI", "Error: ${response.error?.errorMessage}")
122
}
123
}
124
125
// Request specific fields
126
val parameters = Bundle()
127
parameters.putString("fields", "id,name,email,picture.type(large)")
128
request.parameters = parameters
129
130
// Execute the request
131
request.executeAsync()
132
```
133
134
### Custom Graph API Requests
135
136
```kotlin
137
// Make a custom GET request
138
val request = GraphRequest.newGraphPathRequest(
139
AccessToken.getCurrentAccessToken(),
140
"/me/posts"
141
) { response ->
142
if (response.error == null) {
143
val jsonObject = response.jsonObject
144
val postsArray = jsonObject?.optJSONArray("data")
145
// Process posts
146
}
147
}
148
149
// Add parameters for pagination and fields
150
val parameters = Bundle()
151
parameters.putString("fields", "id,message,created_time,likes.summary(true)")
152
parameters.putInt("limit", 25)
153
request.parameters = parameters
154
request.executeAsync()
155
156
// Make a POST request
157
val postData = JSONObject()
158
postData.put("message", "Hello from my app!")
159
postData.put("link", "https://example.com")
160
161
val postRequest = GraphRequest.newPostRequest(
162
AccessToken.getCurrentAccessToken(),
163
"/me/feed",
164
postData
165
) { response ->
166
if (response.error == null) {
167
val postId = response.jsonObject?.getString("id")
168
Log.d("GraphAPI", "Post created with ID: $postId")
169
}
170
}
171
postRequest.executeAsync()
172
```
173
174
## Graph Response
175
176
```kotlin { .api }
177
class GraphResponse(
178
request: GraphRequest,
179
connection: HttpURLConnection?,
180
error: FacebookRequestError?
181
) {
182
val request: GraphRequest
183
val rawResponse: String?
184
val jsonObject: JSONObject?
185
val jsonArray: JSONArray?
186
val error: FacebookRequestError?
187
val connection: HttpURLConnection?
188
189
companion object {
190
fun createResponsesFromString(
191
responseString: String,
192
requests: List<GraphRequest>
193
): List<GraphResponse>
194
195
fun fromHttpConnection(
196
connection: HttpURLConnection,
197
requests: List<GraphRequest>
198
): List<GraphResponse>
199
}
200
}
201
```
202
203
## Batch Requests
204
205
Execute multiple Graph API requests in a single HTTP call:
206
207
```kotlin { .api }
208
class GraphRequestBatch : AbstractList<GraphRequest> {
209
constructor()
210
constructor(requests: Collection<GraphRequest>)
211
constructor(vararg requests: GraphRequest)
212
213
val requests: List<GraphRequest>
214
val timeout: Int
215
val callbackHandler: Handler?
216
val batchApplicationId: String?
217
218
fun setTimeout(timeoutInMilliseconds: Int)
219
fun addCallback(callback: Callback)
220
fun removeCallback(callback: Callback)
221
222
// Execution
223
fun executeAsync(): GraphRequestAsyncTask
224
fun executeAndWait(): List<GraphResponse>
225
226
interface Callback {
227
fun onBatchCompleted(batch: GraphRequestBatch)
228
}
229
230
interface OnProgressCallback {
231
fun onBatchProgress(batch: GraphRequestBatch, current: Long, max: Long)
232
}
233
}
234
```
235
236
### Batch Request Usage
237
238
```kotlin
239
// Create multiple requests
240
val meRequest = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken()) { obj, response ->
241
// Handle user info
242
}
243
244
val friendsRequest = GraphRequest.newMyFriendsRequest(AccessToken.getCurrentAccessToken()) { array, response ->
245
// Handle friends list
246
}
247
248
val postsRequest = GraphRequest.newGraphPathRequest(
249
AccessToken.getCurrentAccessToken(),
250
"/me/posts"
251
) { response ->
252
// Handle posts
253
}
254
255
// Create batch and execute
256
val batch = GraphRequestBatch(meRequest, friendsRequest, postsRequest)
257
batch.addCallback { batch ->
258
Log.d("GraphAPI", "Batch completed with ${batch.size} requests")
259
}
260
batch.executeAsync()
261
```
262
263
## Async Task Management
264
265
```kotlin { .api }
266
class GraphRequestAsyncTask : AsyncTask<Void, Void, List<GraphResponse>> {
267
constructor(connection: HttpURLConnection, vararg requests: GraphRequest)
268
constructor(requests: Collection<GraphRequest>)
269
constructor(batch: GraphRequestBatch)
270
271
val requests: List<GraphRequest>
272
val exception: Exception?
273
274
override fun toString(): String
275
}
276
```
277
278
## Error Handling
279
280
```kotlin { .api }
281
class FacebookRequestError(
282
requestStatusCode: Int,
283
errorCode: Int,
284
errorType: String?,
285
errorMessage: String?
286
) {
287
val requestStatusCode: Int
288
val errorCode: Int
289
val errorType: String?
290
val errorMessage: String?
291
val errorUserMessage: String?
292
val errorUserTitle: String?
293
val requestResult: JSONObject?
294
val batchRequestResult: JSONObject?
295
val exception: FacebookException?
296
297
val category: Category
298
299
enum class Category {
300
LOGIN_RECOVERABLE, // User can fix by logging in again
301
OTHER, // Non-recoverable error
302
TRANSIENT // Temporary error, retry may work
303
}
304
305
companion object {
306
const val INVALID_ERROR_CODE = -1
307
const val INVALID_HTTP_STATUS_CODE = -1
308
}
309
}
310
311
class FacebookGraphResponseException(
312
response: GraphResponse,
313
message: String?
314
) : FacebookException(message) {
315
val graphResponse: GraphResponse
316
}
317
```
318
319
### Error Handling Example
320
321
```kotlin
322
val request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken()) { jsonObject, response ->
323
val error = response.error
324
if (error != null) {
325
when (error.category) {
326
FacebookRequestError.Category.LOGIN_RECOVERABLE -> {
327
// Token expired or invalid, prompt user to login again
328
Log.w("GraphAPI", "Login required: ${error.errorMessage}")
329
AccessToken.setCurrentAccessToken(null)
330
redirectToLogin()
331
}
332
FacebookRequestError.Category.TRANSIENT -> {
333
// Temporary error, retry after delay
334
Log.w("GraphAPI", "Transient error: ${error.errorMessage}")
335
Handler().postDelayed({ request.executeAsync() }, 5000)
336
}
337
FacebookRequestError.Category.OTHER -> {
338
// Permanent error
339
Log.e("GraphAPI", "API error: ${error.errorMessage}")
340
showErrorToUser(error.errorUserMessage ?: error.errorMessage)
341
}
342
}
343
} else {
344
// Success - process the response
345
processUserData(jsonObject)
346
}
347
}
348
```
349
350
## Pagination
351
352
Handle paginated Graph API responses:
353
354
```kotlin
355
fun loadUserPosts(after: String? = null) {
356
val request = GraphRequest.newGraphPathRequest(
357
AccessToken.getCurrentAccessToken(),
358
"/me/posts"
359
) { response ->
360
if (response.error == null) {
361
val jsonObject = response.jsonObject
362
val data = jsonObject?.optJSONArray("data")
363
364
// Process current page of posts
365
processPosts(data)
366
367
// Check for next page
368
val paging = jsonObject?.optJSONObject("paging")
369
val nextPageUrl = paging?.optString("next")
370
val cursors = paging?.optJSONObject("cursors")
371
val afterCursor = cursors?.optString("after")
372
373
if (!nextPageUrl.isNullOrEmpty()) {
374
// Load next page
375
loadUserPosts(afterCursor)
376
}
377
}
378
}
379
380
// Set parameters including pagination cursor
381
val parameters = Bundle()
382
parameters.putString("fields", "id,message,created_time")
383
parameters.putInt("limit", 25)
384
if (after != null) {
385
parameters.putString("after", after)
386
}
387
request.parameters = parameters
388
request.executeAsync()
389
}
390
```
391
392
## File Uploads
393
394
Upload files through the Graph API:
395
396
```kotlin
397
fun uploadPhoto(bitmap: Bitmap, message: String) {
398
val request = GraphRequest.newUploadPhotoRequest(
399
AccessToken.getCurrentAccessToken(),
400
"/me/photos",
401
bitmap,
402
message
403
) { response ->
404
if (response.error == null) {
405
val photoId = response.jsonObject?.getString("id")
406
Log.d("GraphAPI", "Photo uploaded with ID: $photoId")
407
} else {
408
Log.e("GraphAPI", "Upload failed: ${response.error?.errorMessage}")
409
}
410
}
411
request.executeAsync()
412
}
413
414
fun uploadVideo(videoUri: Uri, title: String) {
415
val request = GraphRequest.newUploadVideoRequest(
416
AccessToken.getCurrentAccessToken(),
417
"/me/videos",
418
videoUri,
419
title
420
) { response ->
421
if (response.error == null) {
422
val videoId = response.jsonObject?.getString("id")
423
Log.d("GraphAPI", "Video uploaded with ID: $videoId")
424
}
425
}
426
request.executeAsync()
427
}
428
```
429
430
## Graph API Versioning
431
432
```kotlin
433
// Use specific API version
434
val request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken()) { obj, response ->
435
// Handle response
436
}
437
request.version = "v18.0"
438
request.executeAsync()
439
440
// Set default version for all requests
441
FacebookSdk.setGraphApiVersion("v18.0")
442
```