Skip to main content

Android - Deep Linking

Overview

Deep linking enables direct navigation to specific screens or content within the Q2 Mobile App. This functionality allows external sources and other native modules to programmatically route users to any existing URL path in the application.

Since the app's primary interface is web-based, deep linking essentially allows you to load specific web pages or application states directly, bypassing the need for users to manually navigate through the app's interface.

Deep Linking Methods

The Q2 Mobile App provides two primary approaches for implementing deep links:

  1. ACTION_VIEW Intent - Using Android's standard intent system
  2. sdkUtils Functions - Using our custom SDK utility methods

Using ACTION_VIEW Intent

The Q2 Mobile App includes a built-in deep linking mechanism that responds to ACTION_VIEW intents. When triggered, these intents are processed by the MainActivity, which attempts to navigate to the specified path using the app's internal routing system.

Intent Schema

The deep linking intent follows a specific URI schema that must be constructed correctly. You can use this to create the intent:

private fun setupScheme(context: Context, uri: String? = null): Intent {
var intentScheme = "app://${context.packageName}/open"
if (uri != null) {
intentScheme += "#$uri"
}
return Intent(Intent.ACTION_VIEW, Uri.parse(intentScheme))
}

// Usage example
val intent = setupScheme(context, remoteMessage.data[myUriKey])
sdkUtils.getActivity()?.startActivity(intent)

How It Works

  1. Intent Creation: An ACTION_VIEW intent is created with the properly formatted URI
  2. URI Structure: The URI follows the pattern app://${context.packageName}/open#${path}
  3. Processing: The MainActivity receives the intent and processes the deep link
  4. Navigation: The app navigates to the specified path within the webview

Using sdkUtils Functions

Alternatively, you can use the SDK's built-in utility functions for more direct control over deep linking. The SDK provides two specialized functions depending on the user's authentication state:

// For authenticated users or paths requiring authentication
sdkUtils.loadPathInUuxViewAfterLogon(uri)

// For pre-authentication navigation within the webview
sdkUtils.loadPathInUuxViewBeforeLogon(uri)

Function Differences

FunctionUsage ContextBehavior
loadPathInUuxViewAfterLogon()Post-authentication or auth-required pathsWaits for user authentication before navigation. Use this when in doubt.
loadPathInUuxViewBeforeLogon()Pre-authentication, within webview onlyOnly works before authentication and when already in the webview context.
Recommendation

When uncertain about which function to use, choose loadPathInUuxViewAfterLogon() as it handles most scenarios reliably.

URI Formatting Requirements

Critical URI Formatting Rules

The URI must be formatted exactly as specified below. Incorrect formatting will prevent deep linking from working entirely.

Required URI Format

  • DO: Start at the root of the sub-path
  • DON'T: Include the base URL
  • DON'T: Start with # or /
  • DO: Ensure the URL is valid and sanitized

Valid URI Examples

// ✅ Correct formats
"messages"
"extension/YourExtension/File"
"extension/YourOtherExtension"
"settings/profile"

// ❌ Incorrect formats
"/messages" // Don't start with /
"#messages" // Don't start with #
"https://app.com/messages" // Don't include base URL
"/extension/YourExtension" // Don't start with /

Finding the Correct URI

If you're unsure about the correct URI format for a specific page:

  1. Navigate to the target location using a mobile browser
  2. Copy the URL from the browser's address bar
  3. Remove the base URL (everything before the path)
  4. Remove any prefixed # or / characters
  5. Use the remaining path as your URI parameter

Example URL Conversion

Original URL: https://yourapp.com/#/messages/
Correct URI: messages/

Best Practices

URI Validation

Always validate and sanitize your URIs before using them in deep links:

fun sanitizeUri(uri: String?): String? {
return uri?.let {
it.removePrefix("/")
.removePrefix("#")
.trim()
.takeIf { sanitized -> sanitized.isNotEmpty() }
}
}

// Usage
val cleanUri = sanitizeUri(rawUri)
if (cleanUri != null) {
sdkUtils.loadPathInUuxViewAfterLogon(cleanUri)
}

Error Handling

Implement proper error handling for deep linking operations:

try {
val intent = setupScheme(context, uri)
sdkUtils.getActivity()?.startActivity(intent)
} catch (e: Exception) {
// Handle deep linking failure. Do not force crashes
Log.e("DeepLink", "Failed to open deep link: ${e.message}")
}
  • Test deep links with various URI formats to ensure robustness
  • Verify behavior in both authenticated and unauthenticated states
  • Test on different Android versions and device configurations
  • Validate that invalid URIs are handled gracefully
Important Notes
  • URI formatting is critical for successful deep linking
  • Always sanitize and validate URIs before use
  • Test deep links thoroughly in your target environment
  • Consider the user's authentication state when choosing the appropriate method