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

app-links.mddocs/

App Links

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.

App Link Data

Extract and handle App Link data from incoming intents:

class AppLinkData private constructor() {
    val targetUri: Uri?
    val ref: String?
    val extras: Bundle?
    val argumentBundle: Bundle?
    val promotionCode: String?
    
    companion object {
        // Extract from activity
        fun createFromActivity(activity: Activity): AppLinkData?
        fun createFromAlBundle(appLinkBundle: Bundle): AppLinkData?
        
        // Deferred deep linking
        fun fetchDeferredAppLinkData(
            context: Context,
            callback: CompletionHandler
        )
        
        // Deferred deep linking with specific app link ID
        fun fetchDeferredAppLinkData(
            context: Context,
            applicationId: String?,
            callback: CompletionHandler
        )
    }
    
    interface CompletionHandler {
        fun onDeferredAppLinkDataFetched(appLinkData: AppLinkData?)
    }
}

Basic App Links Usage

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Handle direct app links
        handleAppLink()
        
        // Handle deferred app links (for new installs)
        handleDeferredAppLink()
    }
    
    private fun handleAppLink() {
        val appLinkData = AppLinkData.createFromActivity(this)
        if (appLinkData != null) {
            val targetUri = appLinkData.targetUri
            val ref = appLinkData.ref
            val extras = appLinkData.extras
            val promotionCode = appLinkData.promotionCode
            
            Log.d("AppLinks", "App link received:")
            Log.d("AppLinks", "Target URI: $targetUri")
            Log.d("AppLinks", "Ref: $ref")
            Log.d("AppLinks", "Promotion Code: $promotionCode")
            
            // Navigate to specific content based on app link
            navigateToContent(targetUri, extras)
        }
    }
    
    private fun handleDeferredAppLink() {
        AppLinkData.fetchDeferredAppLinkData(this) { appLinkData ->
            if (appLinkData != null) {
                Log.d("AppLinks", "Deferred app link data received")
                val targetUri = appLinkData.targetUri
                val ref = appLinkData.ref
                
                // Handle deferred deep link (e.g., after app install)
                navigateToContent(targetUri, appLinkData.extras)
            } else {
                Log.d("AppLinks", "No deferred app link data")
            }
        }
    }
    
    private fun navigateToContent(uri: Uri?, extras: Bundle?) {
        if (uri != null) {
            when (uri.path) {
                "/product" -> {
                    val productId = uri.getQueryParameter("id")
                    openProductDetail(productId)
                }
                "/article" -> {
                    val articleId = uri.getQueryParameter("id")
                    openArticle(articleId)
                }
                "/promotion" -> {
                    val promotionCode = extras?.getString("promotion_code")
                    applyPromotion(promotionCode)
                }
                else -> {
                    // Default navigation
                    Log.d("AppLinks", "Unknown app link path: ${uri.path}")
                }
            }
        }
    }
}

App Links Utilities

Utility functions for working with App Links:

class AppLinks {
    companion object {
        // Check if app link data exists in intent
        fun getAppLinkData(intent: Intent): AppLinkData?
        
        // Get target URL from app link data
        fun getTargetUrl(appLinkData: AppLinkData): String?
        
        // Get target URL from intent
        fun getTargetUrlFromIncomingIntent(context: Context, intent: Intent): String?
    }
}

Facebook App Link Resolver

Resolve App Links using Facebook's resolution service:

class FacebookAppLinkResolver : AppLinkResolver {
    constructor()
    constructor(userAgent: String?)
    
    override fun getAppLinkFromUrlInBackground(url: Uri): Task<AppLink>
    override fun getAppLinksFromUrlsInBackground(urls: List<Uri>): Task<Map<Uri, AppLink>>
    
    companion object {
        fun getWebFallbackUrl(url: Uri, userAgent: String?): Task<Uri>
    }
}

App Link Resolution Example

// Using Bolts Tasks framework
fun resolveAppLinks(urls: List<Uri>) {
    val resolver = FacebookAppLinkResolver()
    
    resolver.getAppLinksFromUrlsInBackground(urls)
        .continueWith { task ->
            if (task.isFaulted) {
                Log.e("AppLinks", "Error resolving app links: ${task.error}")
                return@continueWith null
            }
            
            val appLinks = task.result
            appLinks?.forEach { (url, appLink) ->
                Log.d("AppLinks", "URL: $url")
                Log.d("AppLinks", "App Link: ${appLink.sourceUrl}")
                
                // Check available targets
                appLink.targets.forEach { target ->
                    Log.d("AppLinks", "Target: ${target.url}")
                    Log.d("AppLinks", "Package: ${target.packageName}")
                }
                
                // Get web fallback URL
                val webUrl = appLink.webUrl
                Log.d("AppLinks", "Web fallback: $webUrl")
            }
            
            null
        }
}

Bolts App Links Integration

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

// From facebook-bolts module
class AppLink {
    val sourceUrl: Uri
    val targets: List<Target>
    val webUrl: Uri?
    
    data class Target(
        val url: Uri?,
        val appStoreId: String?,
        val packageName: String?,
        val className: String?
    )
}

interface AppLinkResolver {
    fun getAppLinkFromUrlInBackground(url: Uri): Task<AppLink>
    fun getAppLinksFromUrlsInBackground(urls: List<Uri>): Task<Map<Uri, AppLink>>
}

Deep Link Navigation Patterns

Common patterns for handling different types of deep links:

class DeepLinkHandler {
    fun handleAppLink(activity: Activity) {
        val appLinkData = AppLinkData.createFromActivity(activity)
        if (appLinkData != null) {
            val targetUri = appLinkData.targetUri
            val ref = appLinkData.ref
            
            // Track app link usage for analytics
            logAppLinkEvent(ref, targetUri.toString())
            
            // Route based on URI structure
            routeToDestination(activity, targetUri, appLinkData.extras)
        }
    }
    
    private fun routeToDestination(activity: Activity, uri: Uri?, extras: Bundle?) {
        when {
            uri?.host == "product" -> {
                val intent = Intent(activity, ProductDetailActivity::class.java)
                intent.putExtra("product_id", uri.getQueryParameter("id"))
                extras?.let { intent.putExtras(it) }
                activity.startActivity(intent)
            }
            
            uri?.host == "user" -> {
                val intent = Intent(activity, UserProfileActivity::class.java)
                intent.putExtra("user_id", uri.getQueryParameter("id"))
                activity.startActivity(intent)
            }
            
            uri?.host == "share" -> {
                val contentId = uri.getQueryParameter("content_id")
                val contentType = uri.getQueryParameter("type")
                handleSharedContent(activity, contentId, contentType)
            }
            
            else -> {
                // Default fallback
                Log.w("AppLinks", "Unknown app link format: $uri")
                activity.startActivity(Intent(activity, MainActivity::class.java))
            }
        }
    }
    
    private fun logAppLinkEvent(ref: String?, targetUrl: String) {
        val logger = AppEventsLogger.newLogger(context)
        val parameters = Bundle().apply {
            putString("app_link_ref", ref)
            putString("target_url", targetUrl)
            putLong("timestamp", System.currentTimeMillis())
        }
        logger.logEvent("app_link_opened", parameters)
    }
    
    private fun handleSharedContent(activity: Activity, contentId: String?, contentType: String?) {
        if (contentId != null && contentType != null) {
            when (contentType) {
                "article" -> openArticle(activity, contentId)
                "video" -> openVideo(activity, contentId)
                "product" -> openProduct(activity, contentId)
                else -> Log.w("AppLinks", "Unknown content type: $contentType")
            }
        }
    }
}

Deferred Deep Linking

Handle users who install your app from a Facebook link:

class DeferredLinkHandler {
    fun setupDeferredLinking(context: Context) {
        // Fetch deferred app link data on app launch
        AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->
            if (appLinkData != null) {
                // User came from a Facebook link before installing
                handleDeferredLink(context, appLinkData)
                
                // Track deferred conversion
                trackDeferredConversion(appLinkData)
            }
        }
    }
    
    private fun handleDeferredLink(context: Context, appLinkData: AppLinkData) {
        val targetUri = appLinkData.targetUri
        val ref = appLinkData.ref
        val promotionCode = appLinkData.promotionCode
        
        Log.d("DeferredLinks", "Deferred app link data:")
        Log.d("DeferredLinks", "Target: $targetUri")
        Log.d("DeferredLinks", "Ref: $ref")
        Log.d("DeferredLinks", "Promotion: $promotionCode")
        
        // Save deferred link data for later use
        val prefs = context.getSharedPreferences("deferred_links", Context.MODE_PRIVATE)
        prefs.edit().apply {
            putString("deferred_target_uri", targetUri?.toString())
            putString("deferred_ref", ref)
            putString("deferred_promotion", promotionCode)
            putBoolean("has_deferred_link", true)
            apply()
        }
        
        // Apply promotion code if available
        if (promotionCode != null) {
            applyWelcomePromotion(promotionCode)
        }
        
        // Show welcome flow or navigate to specific content
        showDeferredLinkWelcome(context, targetUri)
    }
    
    private fun trackDeferredConversion(appLinkData: AppLinkData) {
        val logger = AppEventsLogger.newLogger(context)
        val parameters = Bundle().apply {
            putString("deferred_link_ref", appLinkData.ref)
            putString("deferred_target", appLinkData.targetUri?.toString())
            putString("promotion_code", appLinkData.promotionCode)
        }
        logger.logEvent("deferred_app_link_conversion", parameters)
    }
    
    fun consumeDeferredLink(context: Context): AppLinkData? {
        val prefs = context.getSharedPreferences("deferred_links", Context.MODE_PRIVATE)
        if (prefs.getBoolean("has_deferred_link", false)) {
            val targetUri = prefs.getString("deferred_target_uri", null)?.let { Uri.parse(it) }
            val ref = prefs.getString("deferred_ref", null)
            val promotion = prefs.getString("deferred_promotion", null)
            
            // Clear the deferred link data
            prefs.edit().clear().apply()
            
            // Create synthetic AppLinkData
            return if (targetUri != null) {
                // Note: This is a simplified approach
                // In reality, you'd need to construct the AppLinkData properly
                createSyntheticAppLinkData(targetUri, ref, promotion)
            } else null
        }
        return null
    }
}

Testing App Links

Test your App Links implementation:

class AppLinkTester {
    fun testAppLinkHandling(activity: Activity) {
        // Create test app link data
        val testUri = Uri.parse("https://example.com/product?id=123&ref=facebook")
        val testExtras = Bundle().apply {
            putString("promotion_code", "WELCOME10")
            putString("campaign", "summer_sale")
        }
        
        // Simulate app link intent
        val testIntent = Intent(Intent.ACTION_VIEW, testUri).apply {
            putExtras(testExtras)
        }
        
        // Test app link extraction
        val appLinkData = AppLinkData.createFromActivity(activity)
        if (appLinkData != null) {
            Log.d("Test", "App link test successful")
            Log.d("Test", "Target: ${appLinkData.targetUri}")
            Log.d("Test", "Ref: ${appLinkData.ref}")
        } else {
            Log.w("Test", "No app link data found")
        }
    }
    
    fun testDeferredLinks(context: Context) {
        // Force fetch deferred app link for testing
        AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->
            if (appLinkData != null) {
                Log.d("Test", "Deferred link test successful")
                Log.d("Test", "Deferred target: ${appLinkData.targetUri}")
            } else {
                Log.d("Test", "No deferred app link data")
            }
        }
    }
}

Integration with Facebook Ads

App Links work seamlessly with Facebook advertising:

// Track app install attribution from Facebook ads
class FacebookAdTracker {
    fun trackInstallAttribution(context: Context) {
        AppLinkData.fetchDeferredAppLinkData(context) { appLinkData ->
            if (appLinkData != null) {
                val ref = appLinkData.ref
                
                // Track attribution based on ref parameter
                when {
                    ref?.startsWith("ad_") == true -> {
                        // User came from Facebook ad
                        trackAdConversion(ref, appLinkData)
                    }
                    ref?.startsWith("post_") == true -> {
                        // User came from Facebook post
                        trackPostConversion(ref, appLinkData)
                    }
                    ref?.startsWith("page_") == true -> {
                        // User came from Facebook page
                        trackPageConversion(ref, appLinkData)
                    }
                }
            }
        }
    }
    
    private fun trackAdConversion(ref: String, appLinkData: AppLinkData) {
        val logger = AppEventsLogger.newLogger(context)
        val parameters = Bundle().apply {
            putString("fb_ad_ref", ref)
            putString("target_url", appLinkData.targetUri?.toString())
            putString("promotion_code", appLinkData.promotionCode)
        }
        logger.logEvent("fb_ad_install_conversion", parameters)
    }
}

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