CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-facebook-android--facebook-android-sdk

Facebook SDK for Android providing comprehensive integration with Facebook platform features including Login, Sharing, Messenger, App Links, Analytics, and Graph API

Pending
Overview
Eval results
Files

bolts-tasks.mddocs/

Asynchronous Tasks (Bolts)

The Bolts framework provides a powerful task management system for handling asynchronous operations with continuation support, error handling, and cancellation. It enables chaining of asynchronous operations and provides a clean alternative to nested callbacks.

Task

The core Task class for managing asynchronous operations:

class Task<TResult> private constructor() {
    // Task state
    val isCompleted: Boolean
    val isCancelled: Boolean
    val isFaulted: Boolean
    val result: TResult?
    val error: Exception?
    
    // Continuation methods
    fun <TContinuationResult> continueWith(
        continuation: Continuation<TResult, TContinuationResult>
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> continueWith(
        continuation: Continuation<TResult, TContinuationResult>,
        executor: Executor
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> continueWithTask(
        continuation: Continuation<TResult, Task<TContinuationResult>>
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> continueWithTask(
        continuation: Continuation<TResult, Task<TContinuationResult>>,
        executor: Executor
    ): Task<TContinuationResult>
    
    // Success continuations
    fun <TContinuationResult> onSuccess(
        continuation: Continuation<TResult, TContinuationResult>
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> onSuccess(
        continuation: Continuation<TResult, TContinuationResult>,
        executor: Executor
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> onSuccessTask(
        continuation: Continuation<TResult, Task<TContinuationResult>>
    ): Task<TContinuationResult>
    
    fun <TContinuationResult> onSuccessTask(
        continuation: Continuation<TResult, Task<TContinuationResult>>,
        executor: Executor
    ): Task<TContinuationResult>
    
    // Wait methods
    fun waitForCompletion()
    fun waitForCompletion(duration: Long, timeUnit: TimeUnit): Boolean
    
    companion object {
        // Task creation
        fun <TResult> call(callable: Callable<TResult>): Task<TResult>
        fun <TResult> call(callable: Callable<TResult>, executor: Executor): Task<TResult>
        fun <TResult> callInBackground(callable: Callable<TResult>): Task<TResult>
        fun <TResult> forResult(result: TResult): Task<TResult>
        fun <TResult> forError(error: Exception): Task<TResult>
        fun <TResult> cancelled(): Task<TResult>
        
        // Task composition
        fun <TResult> whenAll(tasks: Collection<Task<TResult>>): Task<List<TResult>>
        fun whenAllResult(tasks: Collection<Task<*>>): Task<Void>
        fun <TResult> whenAny(tasks: Collection<Task<TResult>>): Task<Task<TResult>>
        fun whenAnyResult(tasks: Collection<Task<*>>): Task<Task<*>>
        
        // Delay
        fun delay(millis: Long): Task<Void>
        fun delay(millis: Long, cancellationToken: CancellationToken): Task<Void>
    }
}

interface Continuation<TTaskResult, TContinuationResult> {
    @Throws(Exception::class)
    fun then(task: Task<TTaskResult>): TContinuationResult
}

Basic Task Usage

class TaskExamples {
    
    fun basicTaskUsage() {
        // Create a task from a callable
        val task = Task.call {
            // Simulate some work
            Thread.sleep(1000)
            "Task completed successfully"
        }
        
        // Continue with the result
        task.continueWith { task ->
            if (task.isFaulted) {
                Log.e("Task", "Task failed: ${task.error?.message}")
                "Error occurred"
            } else {
                val result = task.result
                Log.d("Task", "Task result: $result")
                result?.uppercase()
            }
        }.continueWith { task ->
            val finalResult = task.result
            Log.d("Task", "Final result: $finalResult")
            finalResult
        }
    }
    
    fun backgroundTaskUsage() {
        // Execute task in background
        Task.callInBackground {
            // Perform network request or database operation
            fetchDataFromApi()
        }.onSuccess { result ->
            // This runs on the main thread by default
            Log.d("Task", "Data fetched: $result")
            updateUI(result)
        }.continueWith { task ->
            if (task.isFaulted) {
                Log.e("Task", "Background task failed: ${task.error?.message}")
                handleError(task.error)
            }
            null
        }
    }
    
    fun chainedTasksExample() {
        // Chain multiple asynchronous operations
        Task.callInBackground {
            authenticateUser()
        }.onSuccessTask { authResult ->
            // Return another task
            Task.callInBackground {
                fetchUserProfile(authResult.userId)
            }
        }.onSuccessTask { profile ->
            // Another chained operation
            Task.callInBackground {
                loadUserPreferences(profile.id)
            }
        }.onSuccess { preferences ->
            // Final success handler
            Log.d("Task", "All operations completed")
            setupUserSession(preferences)
        }.continueWith { task ->
            if (task.isFaulted) {
                Log.e("Task", "Chain failed: ${task.error?.message}")
                showLoginScreen()
            }
            null
        }
    }
}

Task Completion Source

Manual control over task completion:

class TaskCompletionSource<TResult> {
    val task: Task<TResult>
    val isCancellationRequested: Boolean
    
    fun setResult(result: TResult): Boolean
    fun trySetResult(result: TResult): Boolean
    fun setError(error: Exception): Boolean
    fun trySetError(error: Exception): Boolean
    fun setCancelled(): Boolean
    fun trySetCancelled(): Boolean
}

Task Completion Source Usage

class ManualTaskControl {
    
    fun createManualTask(): Task<String> {
        val tcs = TaskCompletionSource<String>()
        
        // Simulate async operation with manual completion
        Thread {
            try {
                Thread.sleep(2000)
                // Manually complete the task
                tcs.setResult("Manual task completed")
            } catch (e: InterruptedException) {
                tcs.setError(e)
            }
        }.start()
        
        return tcs.task
    }
    
    fun createConditionalTask(condition: Boolean): Task<String> {
        val tcs = TaskCompletionSource<String>()
        
        if (condition) {
            tcs.setResult("Condition met")
        } else {
            tcs.setError(IllegalStateException("Condition not met"))
        }
        
        return tcs.task
    }
    
    fun createTimeoutTask(timeoutMs: Long): Task<String> {
        val tcs = TaskCompletionSource<String>()
        
        // Set up timeout
        Handler(Looper.getMainLooper()).postDelayed({
            if (!tcs.task.isCompleted) {
                tcs.setError(TimeoutException("Task timed out"))
            }
        }, timeoutMs)
        
        // Simulate work
        Thread {
            try {
                Thread.sleep(timeoutMs + 1000) // Will timeout
                tcs.trySetResult("Work completed")
            } catch (e: Exception) {
                tcs.trySetError(e)
            }
        }.start()
        
        return tcs.task
    }
}

Cancellation Support

Handle task cancellation with cancellation tokens:

class CancellationToken {
    val isCancellationRequested: Boolean
    
    fun throwIfCancellationRequested()
    fun register(action: Runnable): CancellationTokenRegistration
}

class CancellationTokenSource {
    val token: CancellationToken
    val isCancellationRequested: Boolean
    
    fun cancel()
    fun cancelAfter(delayMs: Long)
    fun close()
}

class CancellationTokenRegistration {
    fun close()
}

Cancellation Usage

class CancellationExamples {
    
    fun cancellableTask() {
        val cancellationSource = CancellationTokenSource()
        val cancellationToken = cancellationSource.token
        
        val task = Task.call({
            // Long running operation
            for (i in 1..100) {
                // Check for cancellation
                cancellationToken.throwIfCancellationRequested()
                
                // Simulate work
                Thread.sleep(100)
                Log.d("Task", "Progress: $i/100")
            }
            "Task completed"
        }, BoltsExecutors.background())
        
        // Cancel after 5 seconds
        Handler(Looper.getMainLooper()).postDelayed({
            cancellationSource.cancel()
            Log.d("Task", "Cancellation requested")
        }, 5000)
        
        task.continueWith { task ->
            when {
                task.isCancelled -> Log.d("Task", "Task was cancelled")
                task.isFaulted -> Log.e("Task", "Task failed: ${task.error?.message}")
                else -> Log.d("Task", "Task completed: ${task.result}")
            }
            null
        }
    }
    
    fun cancellationWithCleanup() {
        val cancellationSource = CancellationTokenSource()
        
        // Register cleanup action
        val registration = cancellationSource.token.register {
            Log.d("Task", "Performing cleanup...")
            cleanupResources()
        }
        
        val task = Task.callInBackground {
            try {
                performLongRunningOperation(cancellationSource.token)
            } finally {
                registration.close()
            }
        }
        
        // Auto-cancel after timeout
        cancellationSource.cancelAfter(10000) // 10 seconds
        
        return task
    }
}

Task Executors

Control where tasks execute:

object BoltsExecutors {
    fun background(): Executor
    fun immediate(): Executor
}

object AndroidExecutors {
    fun mainThread(): Executor
    fun uiThread(): Executor
}

Executor Usage

class ExecutorExamples {
    
    fun executorControlExample() {
        // Background task
        Task.call({
            // Heavy computation
            performCpuIntensiveWork()
        }, BoltsExecutors.background())
        .continueWith({ task ->
            // Process result on background thread
            processResult(task.result)
        }, BoltsExecutors.background())
        .continueWith({ task ->
            // Update UI on main thread
            updateUI(task.result)
            null
        }, AndroidExecutors.mainThread())
    }
    
    fun immediateExecutorExample() {
        // Task that executes immediately on current thread
        val result = Task.forResult("immediate result")
        
        result.continueWith({ task ->
            Log.d("Task", "This runs immediately: ${task.result}")
            null
        }, BoltsExecutors.immediate())
    }
}

Task Composition

Combine multiple tasks:

class TaskComposition {
    
    fun parallelTasksExample() {
        val task1 = Task.callInBackground { fetchUserData() }
        val task2 = Task.callInBackground { fetchUserPreferences() }
        val task3 = Task.callInBackground { fetchUserSettings() }
        
        // Wait for all tasks to complete
        Task.whenAll(listOf(task1, task2, task3))
            .onSuccess { results ->
                val userData = results[0]
                val preferences = results[1] 
                val settings = results[2]
                
                // Combine all results
                setupUserSession(userData, preferences, settings)
            }
            .continueWith { task ->
                if (task.isFaulted) {
                    Log.e("Task", "One or more tasks failed: ${task.error?.message}")
                    handleError(task.error)
                }
                null
            }
    }
    
    fun raceConditionExample() {
        val cacheTask = Task.callInBackground { loadFromCache() }
        val networkTask = Task.callInBackground { loadFromNetwork() }
        
        // Use whichever completes first
        Task.whenAny(listOf(cacheTask, networkTask))
            .onSuccess { firstCompletedTask ->
                val winningTask = firstCompletedTask
                if (!winningTask.isFaulted) {
                    Log.d("Task", "Using result from fastest source")
                    processData(winningTask.result)
                } else {
                    Log.w("Task", "Fastest task failed, waiting for other...")
                    // Handle the case where first task failed
                }
            }
    }
    
    fun conditionalChainingExample() {
        Task.callInBackground {
            checkUserAuthentication()
        }.onSuccessTask { isAuthenticated ->
            if (isAuthenticated) {
                // User is authenticated, fetch protected data
                Task.callInBackground { fetchProtectedUserData() }
            } else {
                // User not authenticated, redirect to login
                Task.forResult(null)
            }
        }.onSuccess { protectedData ->
            if (protectedData != null) {
                displayUserData(protectedData)
            } else {
                showLoginScreen()
            }
        }
    }
}

Error Handling Patterns

Advanced error handling with tasks:

class TaskErrorHandling {
    
    fun retryPattern() {
        fun attemptOperation(attempt: Int = 1): Task<String> {
            return Task.callInBackground {
                if (Math.random() < 0.7 && attempt < 3) {
                    throw IOException("Network error (attempt $attempt)")
                }
                "Operation successful on attempt $attempt"
            }.continueWithTask { task ->
                if (task.isFaulted && attempt < 3) {
                    Log.w("Task", "Attempt $attempt failed, retrying...")
                    Task.delay(1000 * attempt).continueWithTask {
                        attemptOperation(attempt + 1)
                    }
                } else {
                    Task.forResult(task.result ?: throw task.error!!)
                }
            }
        }
        
        attemptOperation().onSuccess { result ->
            Log.d("Task", "Final result: $result")
        }.continueWith { task ->
            if (task.isFaulted) {
                Log.e("Task", "All retry attempts failed: ${task.error?.message}")
            }
            null
        }
    }
    
    fun fallbackPattern() {
        Task.callInBackground {
            fetchFromPrimarySource()
        }.continueWithTask { task ->
            if (task.isFaulted) {
                Log.w("Task", "Primary source failed, trying fallback...")
                Task.callInBackground { fetchFromFallbackSource() }
            } else {
                Task.forResult(task.result)
            }
        }.continueWithTask { task ->
            if (task.isFaulted) {
                Log.w("Task", "Fallback failed, using cache...")
                Task.callInBackground { fetchFromCache() }
            } else {
                Task.forResult(task.result)
            }
        }.onSuccess { result ->
            Log.d("Task", "Data retrieved: $result")
            processData(result)
        }.continueWith { task ->
            if (task.isFaulted) {
                Log.e("Task", "All sources failed: ${task.error?.message}")
                showErrorMessage("Unable to load data")
            }
            null
        }
    }
    
    fun timeoutPattern() {
        val timeoutTask = Task.delay(5000).continueWith {
            throw TimeoutException("Operation timed out")
        }
        
        val operationTask = Task.callInBackground {
            performSlowOperation()
        }
        
        Task.whenAny(listOf(operationTask, timeoutTask))
            .onSuccessTask { firstCompleted ->
                if (firstCompleted == operationTask && !operationTask.isFaulted) {
                    Task.forResult(operationTask.result)
                } else {
                    Task.forError<String>(TimeoutException("Operation timed out"))
                }
            }
            .onSuccess { result ->
                Log.d("Task", "Operation completed within timeout: $result")
            }
            .continueWith { task ->
                if (task.isFaulted) {
                    Log.e("Task", "Operation failed or timed out: ${task.error?.message}")
                }
                null
            }
    }
}

Integration with Facebook SDK

Using Bolts tasks with Facebook SDK operations:

class FacebookBoltsIntegration {
    
    fun facebookLoginWithTasks(): Task<AccessToken> {
        val tcs = TaskCompletionSource<AccessToken>()
        
        val loginManager = LoginManager.getInstance()
        loginManager.registerCallback(callbackManager, object : FacebookCallback<LoginResult> {
            override fun onSuccess(result: LoginResult) {
                tcs.setResult(result.accessToken)
            }
            
            override fun onCancel() {
                tcs.setError(FacebookOperationCanceledException("Login cancelled"))
            }
            
            override fun onError(error: FacebookException) {
                tcs.setError(error)
            }
        })
        
        loginManager.logIn(activity, listOf("email", "public_profile"))
        return tcs.task
    }
    
    fun graphRequestWithTasks(graphPath: String): Task<JSONObject> {
        val tcs = TaskCompletionSource<JSONObject>()
        
        val request = GraphRequest.newGraphPathRequest(
            AccessToken.getCurrentAccessToken(),
            graphPath
        ) { response ->
            if (response.error != null) {
                tcs.setError(FacebookGraphResponseException(response, response.error!!.errorMessage))
            } else {
                response.jsonObject?.let { 
                    tcs.setResult(it)
                } ?: tcs.setError(FacebookException("Empty response"))
            }
        }
        
        request.executeAsync()
        return tcs.task
    }
    
    fun completeUserSetupChain(): Task<Void> {
        return facebookLoginWithTasks()
            .onSuccessTask { accessToken ->
                graphRequestWithTasks("/me?fields=id,name,email")
            }
            .onSuccessTask { userInfo ->
                Task.callInBackground {
                    saveUserInfo(userInfo)
                }
            }
            .onSuccessTask {
                Task.callInBackground {
                    loadUserPreferences()
                }
            }
            .onSuccess { preferences ->
                setupUserSession(preferences)
                null
            }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-facebook-android--facebook-android-sdk

docs

app-events.md

app-links.md

bolts-tasks.md

core-authentication.md

gaming.md

graph-api.md

index.md

login.md

messenger.md

sharing.md

tile.json