馃摉 Przegl膮d

Modu艂 DeepLinks pozwala na 艂atw膮 obs艂ug臋 deep link贸w w aplikacji Android. Obs艂uguje wzorce URL z parametrami, walidacj臋 scheme i host贸w oraz automatyczne wyci膮ganie parametr贸w z 艣cie偶ki i query string.

Szybki przyk艂ad
// Rejestracja handlera
ADict.DeepLinks.register("product/{id}") { params ->
    val productId = params["id"]
    openProduct(productId)
}

// W Activity.onCreate
ADict.DeepLinks.handle(intent)

鈿欙笍 Konfiguracja

configure(schemes, hosts)

Skonfiguruj dozwolone schematy URI i hosty.

Parametry:

  • schemes: List<String> - Lista dozwolonych schemat贸w (domy艣lnie: ["https", "http"])
  • hosts: List<String> - Lista dozwolonych host贸w (pusta = wszystkie)
Przyk艂ad konfiguracji
// Konfiguracja dla aplikacji
ADict.DeepLinks.configure(
    schemes = listOf("https", "http", "myapp"),
    hosts = listOf("myapp.com", "www.myapp.com")
)

// W艂asny scheme (np. myapp://product/123)
ADict.DeepLinks.configure(
    schemes = listOf("myapp"),
    hosts = emptyList() // Wszystkie hosty
)
鈿狅笍 Uwaga: Je艣li skonfigurujesz hosty, linki z innych host贸w b臋d膮 odrzucane. Pusta lista host贸w oznacza akceptacj臋 wszystkich.

馃摑 Rejestracja handler贸w

register(pattern, handler)

Zarejestruj handler dla wzorca URL.

Parametry:

  • pattern: String - Wzorzec URL z parametrami w nawiasach klamrowych
  • handler: (Map<String, String>) -> Unit - Callback z map膮 parametr贸w

Sk艂adnia wzorc贸w

Wzorzec Przyk艂adowy URL Parametry
product/{id} /product/123 {"id": "123"}
user/{userId}/post/{postId} /user/42/post/99 {"userId": "42", "postId": "99"}
search?q={query} /search?q=kotlin {"query": "kotlin"}
category/{cat}/item/{id} /category/electronics/item/456 {"cat": "electronics", "id": "456"}
Rejestracja wielu handler贸w
// Strona produktu
ADict.DeepLinks.register("product/{id}") { params ->
    val productId = params["id"] ?: return@register
    navigateToProduct(productId)
}

// Profil u偶ytkownika
ADict.DeepLinks.register("user/{userId}") { params ->
    val userId = params["userId"] ?: return@register
    navigateToProfile(userId)
}

// Post u偶ytkownika
ADict.DeepLinks.register("user/{userId}/post/{postId}") { params ->
    val userId = params["userId"]
    val postId = params["postId"]
    navigateToPost(userId, postId)
}

// Wyszukiwanie z query params
ADict.DeepLinks.register("search") { params ->
    val query = params["q"] ?: ""
    val category = params["category"]
    searchProducts(query, category)
}

// Domy艣lny handler dla niedopasowanych link贸w
ADict.DeepLinks.setDefaultHandler { uri ->
    Log.d("DeepLinks", "Nieobs艂ugiwany link: $uri")
    openWebView(uri.toString())
    true // true = obs艂u偶ono, false = nie obs艂u偶ono
}

unregister(pattern)

Usu艅 zarejestrowany handler.

Parametry:

  • pattern: String - Wzorzec do usuni臋cia

clear()

Wyczy艣膰 wszystkie zarejestrowane handlery i domy艣lny handler.

馃攧 Obs艂uga link贸w

handle(intent: Intent?): DeepLinkResult

Obs艂u偶 Intent zawieraj膮cy deep link.

Parametry:

  • intent: Intent? - Intent z Activity

Zwraca:

DeepLinkResult - Wynik obs艂ugi linku

handle(uri: Uri): DeepLinkResult

Obs艂u偶 URI bezpo艣rednio.

handle(url: String): DeepLinkResult

Obs艂u偶 string URL.

Obs艂uga w Activity
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Obs艂uga deep linka z onCreate
        handleDeepLink(intent)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // Obs艂uga deep linka gdy Activity jest ju偶 uruchomione
        intent?.let { handleDeepLink(it) }
    }

    private fun handleDeepLink(intent: Intent) {
        val result = ADict.DeepLinks.handle(intent)

        when {
            result.matched -> {
                Log.d("DeepLinks", "Dopasowano wzorzec: ${result.pattern}")
                Log.d("DeepLinks", "Parametry: ${result.params}")
            }
            result.uri != null -> {
                Log.d("DeepLinks", "Niedopasowany link: ${result.uri}")
            }
            else -> {
                Log.d("DeepLinks", "Brak deep linka w Intent")
            }
        }
    }
}

馃И Testowanie

test(uri: Uri): DeepLinkResult

Testuj dopasowanie URL bez wykonywania handlera.

Parametry:

  • uri: Uri - URI do przetestowania

Zwraca:

DeepLinkResult - Wynik testu (bez wywo艂ania handlera)

test(url: String): DeepLinkResult

Testuj dopasowanie string URL.

Testowanie dopasowa艅
// Testowanie bez wykonywania akcji
val result1 = ADict.DeepLinks.test("https://myapp.com/product/123")
println("Matched: ${result1.matched}")          // true
println("Pattern: ${result1.pattern}")          // "product/{id}"
println("Params: ${result1.params}")            // {id=123}

val result2 = ADict.DeepLinks.test("https://myapp.com/unknown/path")
println("Matched: ${result2.matched}")          // false

// Przydatne do unit test贸w
@Test
fun testProductDeepLink() {
    ADict.DeepLinks.register("product/{id}") { }

    val result = ADict.DeepLinks.test("https://myapp.com/product/456")

    assertTrue(result.matched)
    assertEquals("product/{id}", result.pattern)
    assertEquals("456", result.params["id"])
}

馃敡 Budowanie URL

build(pattern, params, scheme, host): String

Wygeneruj deep link URL z wzorca i parametr贸w.

Parametry:

  • pattern: String - Wzorzec URL
  • params: Map<String, String> - Mapa parametr贸w
  • scheme: String - Schemat URL (domy艣lnie: "https")
  • host: String - Host URL (domy艣lnie: "")

Zwraca:

String - Wygenerowany URL

Budowanie URL
// Budowanie URL produktu
val productUrl = ADict.DeepLinks.build(
    pattern = "/product/{id}",
    params = mapOf("id" to "123"),
    scheme = "https",
    host = "myapp.com"
)
// Wynik: https://myapp.com/product/123

// Budowanie URL z wieloma parametrami
val postUrl = ADict.DeepLinks.build(
    pattern = "/user/{userId}/post/{postId}",
    params = mapOf("userId" to "42", "postId" to "99"),
    scheme = "myapp",
    host = ""
)
// Wynik: myapp:///user/42/post/99

// Bez hosta (relatywny URL)
val relativeUrl = ADict.DeepLinks.build(
    pattern = "/search?q={query}",
    params = mapOf("query" to "kotlin android")
)
// Wynik: /search?q=kotlin%20android

getRegisteredPatterns(): List<String>

Pobierz list臋 wszystkich zarejestrowanych wzorc贸w.

Zwraca:

List<String> - Lista wzorc贸w

馃摝 Klasy danych

data class DeepLinkResult

Wynik parsowania deep linka.

  • matched Boolean Czy link zosta艂 dopasowany do wzorca
  • pattern String? Dopasowany wzorzec (null je艣li nie dopasowano)
  • params Map<String, String> Mapa wyci膮gni臋tych parametr贸w
  • uri Uri? Oryginalny URI

data class DeepLinkHandler

Wewn臋trzna klasa reprezentuj膮ca zarejestrowany handler.

  • pattern String Oryginalny wzorzec
  • regex Pattern Skompilowany regex
  • paramNames List<String> Lista nazw parametr贸w
  • callback (Map<String, String>) -> Unit Funkcja callback

馃挕 Przyk艂ady praktyczne

E-commerce App

Pe艂na konfiguracja dla sklepu
class ShopApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        ADict.init(this, BuildConfig.DEBUG)
        setupDeepLinks()
    }

    private fun setupDeepLinks() {
        ADict.DeepLinks.configure(
            schemes = listOf("https", "myshop"),
            hosts = listOf("myshop.com", "www.myshop.com")
        )

        // Produkt
        ADict.DeepLinks.register("product/{productId}") { params ->
            val productId = params["productId"] ?: return@register
            Navigator.navigateToProduct(productId)

            // Analytics
            ADict.Analytics.log("deep_link_product", mapOf(
                "product_id" to productId
            ))
        }

        // Kategoria
        ADict.DeepLinks.register("category/{categoryId}") { params ->
            val categoryId = params["categoryId"] ?: return@register
            Navigator.navigateToCategory(categoryId)
        }

        // Wyszukiwanie
        ADict.DeepLinks.register("search") { params ->
            val query = params["q"] ?: ""
            val category = params["category"]
            val sort = params["sort"] ?: "relevance"
            Navigator.navigateToSearch(query, category, sort)
        }

        // Koszyk
        ADict.DeepLinks.register("cart") { _ ->
            Navigator.navigateToCart()
        }

        // Promocja
        ADict.DeepLinks.register("promo/{code}") { params ->
            val promoCode = params["code"] ?: return@register
            applyPromoCode(promoCode)
            Navigator.navigateToCart()
        }

        // Domy艣lny handler
        ADict.DeepLinks.setDefaultHandler { uri ->
            // Otw贸rz w WebView dla nieznanych link贸w
            Navigator.navigateToWebView(uri.toString())
            true
        }
    }
}

Social Media App

Konfiguracja dla social media
private fun setupDeepLinks() {
    ADict.DeepLinks.configure(
        schemes = listOf("https", "socialapp"),
        hosts = listOf("socialapp.io")
    )

    // Profil u偶ytkownika
    ADict.DeepLinks.register("user/{username}") { params ->
        val username = params["username"] ?: return@register
        viewModel.loadUserProfile(username)
    }

    // Profil po ID
    ADict.DeepLinks.register("users/{userId}") { params ->
        val userId = params["userId"] ?: return@register
        viewModel.loadUserProfileById(userId)
    }

    // Post
    ADict.DeepLinks.register("post/{postId}") { params ->
        val postId = params["postId"] ?: return@register
        viewModel.loadPost(postId)
    }

    // Post u偶ytkownika
    ADict.DeepLinks.register("user/{username}/post/{postId}") { params ->
        val username = params["username"]
        val postId = params["postId"] ?: return@register
        viewModel.loadPost(postId)
    }

    // Hashtag
    ADict.DeepLinks.register("hashtag/{tag}") { params ->
        val tag = params["tag"] ?: return@register
        viewModel.searchByHashtag(tag)
    }

    // Wiadomo艣膰 bezpo艣rednia
    ADict.DeepLinks.register("dm/{conversationId}") { params ->
        val conversationId = params["conversationId"] ?: return@register
        if (isLoggedIn()) {
            viewModel.openConversation(conversationId)
        } else {
            saveDeepLinkForAfterLogin()
            showLoginScreen()
        }
    }
}

Integracja z AndroidManifest

AndroidManifest.xml
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask"
    android:exported="true">

    <!-- Standard launcher intent -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <!-- HTTP/HTTPS deep links -->
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="https" />
        <data android:scheme="http" />
        <data android:host="myapp.com" />
        <data android:host="www.myapp.com" />
    </intent-filter>

    <!-- Custom scheme -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="myapp" />
    </intent-filter>
</activity>

馃摎 API Reference

Metoda Opis Zwraca
configure(schemes, hosts) Konfiguruj dozwolone schematy i hosty Unit
register(pattern, handler) Zarejestruj handler dla wzorca Unit
unregister(pattern) Usu艅 handler Unit
setDefaultHandler(handler) Ustaw domy艣lny handler Unit
clear() Wyczy艣膰 wszystkie handlery Unit
handle(intent) Obs艂u偶 Intent DeepLinkResult
handle(uri) Obs艂u偶 URI DeepLinkResult
handle(url) Obs艂u偶 string URL DeepLinkResult
test(uri) Testuj bez wykonywania DeepLinkResult
build(pattern, params, ...) Wygeneruj URL String
getRegisteredPatterns() Pobierz list臋 wzorc贸w List<String>