Plugin
Core Capabilities¶
The primary responsibilities and capabilities of the DeepMatch Gradle plugin are:
-
YAML Configuration Parsing:
- The plugin automatically locates and reads all deeplink spec files from:
- module root:
.deeplinks.ymland*.deeplinks.yml src/<variant>/:.deeplinks.ymland*.deeplinks.yml
- module root:
- Sources are merged in deterministic order: root files first, then variant files.
- If the same spec
nameappears in multiple sources, the later source overrides the earlier one. - This means a build-type/variant spec overrides a module-root spec with the same
name.
- If the same spec
- It parses the YAML content, validating its structure against the expected format (implicitly defined by how it generates code and manifest entries, aligning with the
DeeplinkConfigstructure). - Each spec must define at least one
scheme;hostis optional and can be omitted for hostless deeplinks. - Spec
namevalues must be unique within the same source file; duplicates fail early with a clear plugin error.
- The plugin automatically locates and reads all deeplink spec files from:
-
Android Manifest Generation:
- Based on the parsed
deeplinkSpecsfrom your YAML file, the plugin dynamically generates the necessary<intent-filter>entries within your app'sAndroidManifest.xml. - For each
DeeplinkConfigentry in your YAML, it creates an<activity>(or merges with an existing one if theactivityname matches) and adds an<intent-filter>to it. - Path attributes are selected automatically based on spec shape:
- static paths ->
android:path(with trailing-slash variant) - typed-at-end paths ->
android:pathPrefix - typed-in-middle paths ->
android:pathPattern(+android:pathAdvancedPatternwhencompileSdk >= 31)
- static paths ->
- For
autoVerify: truespecs that mix web and custom schemes (for example,[https, app]), generated manifest output is split into separate intent filters so only web schemes are auto-verified. - Hostless specs omit
android:host. Whenportis declared,android:portis generated. Hostless custom-scheme entries include targeted lint suppression (tools:ignore="AppLinkUrlError") for AGP 9+ lint compatibility. - Query params and fragment constraints are not emitted in manifest filters (they are runtime-validated by
DeeplinkProcessor). - Generated deeplink activities include
android:exported="true"andtools:node="merge"for Android 12+ and merge-friendly behavior. - This automation means you do not need to manually write or maintain these
<intent-filter>tags in your mainAndroidManifest.xmlfor the deep links defined in your YAML. The plugin handles keeping them in sync with your YAML configuration. - The generated manifest entries are typically merged into the final manifest during the build process (e.g., visible in
app/build/intermediates/merged_manifests/debug/AndroidManifest.xml).
- Based on the parsed
-
Code Generation (
DeeplinkSpecs):- The plugin generates Kotlin source code, most notably a class named something like
[DeeplinkName]DeeplinkSpecs(the exact name might vary based on the deeplink name in the.ymlfile). - The plugin also generates a params class for every deeplink spec, including static-only specs.
- It additionally generates a module-level sealed interface (for example, module
app->AppDeeplinkParams) implemented by all generated params classes, enabling exhaustivewhenmatching in app code. - It generates a module-level processor object (for example, module
app->AppDeeplinkProcessor) wired with all generated specs so no manual registration is required.
- The plugin generates Kotlin source code, most notably a class named something like
-
Integration with Build Process:
- The plugin hooks into the Android Gradle Plugin's build lifecycle.
- Its tasks (like YAML parsing, manifest generation, code generation) typically run before Java/Kotlin compilation, ensuring that the generated code and manifest entries are available when the rest of your app's code (including the codegen process) is processed.
- For composed multi-module setups, the plugin also validates URI-shape collisions and fails fast when two modules define the same normalized deeplink shape.
-
Configuration Options:
- The plugin provides a DSL (Domain Specific Language) extension in your
build.gradle(deepMatch { ... }block) to customize its behavior:- generateManifestFiles: Specifying whether or not the plugin should generate
AndroidManifest.xmlfile based on the deeplink configyamlfile. - report.enabled: Enables generation of a standalone deeplink HTML report.
- report.output: Optional output file override for the generated report.
- generateManifestFiles: Specifying whether or not the plugin should generate
- The plugin provides a DSL (Domain Specific Language) extension in your
Benefits of Using the Plugin¶
- Single Source of Truth: Your discovered deeplink YAML sources become the definitive source for all deep link definitions.
- Reduced Boilerplate: No need to manually write complex and error-prone
<intent-filter>tags in the manifest. - Consistency: Ensures that your manifest and the runtime parsing logic are always in sync with your declared specifications.
- Improved Maintainability: Adding, removing, or modifying deep links is as simple as editing the YAML file and rebuilding.
- Build-Time Checks (Implicit): While not a full validation suite, the parsing step can catch basic syntax errors in your YAML file early in the build process.
Getting Started¶
-
Apply the plugin alongside your Android plugin:
-
Configure the extension in the same module:
-
Add one or more deeplink YAML files:
- module root:
.deeplinks.ymlor*.deeplinks.yml - variant-specific:
src/<variant>/.deeplinks.ymlorsrc/<variant>/*.deeplinks.ymlSeedeeplink-specs.mdfor the full schema.
- module root:
During the build the plugin generates Kotlin sources under build/generated/ and, when enabled, a manifest snippet under build/generated/manifests/<variant>/AndroidManifest.xml.
For multi-module behavior and precedence, see Composite Specs.
Generated Artifacts¶
<ModuleName>DeeplinkParams.kt— module-level sealed interface implemented by generated params classes.<ModuleName>DeeplinkProcessor.kt— module-level processor object extendingDeeplinkProcessorand preconfigured with all generated specs. When dependent modules also apply DeepMatch, this generated object extendsCompositeDeeplinkProcessorand composes local specs with discovered module processors in order.*DeeplinkSpecs.kt— exposes aDeeplinkSpecproperty per configuration entry. Generated specs usepathParamsas an ordered list to preserve YAML-declared path segment order.*DeeplinkParams.kt— params class emitted for every deeplink spec. When a spec has typed values, generated constructor properties are strongly typed. Query params markedrequired: trueare generated as non-null properties; optional query params are generated as nullable properties.- Generated manifest file — contains
<intent-filter>definitions that Gradle merges into the final manifest.
Available Tasks¶
Task details are documented in Tasks, including:
generate<Variant>DeeplinkSpecsgenerate<Variant>DeeplinksManifestvalidateDeeplinksgenerateDeeplinkReport
Testing & CI¶
./gradlew publishToMavenLocal # Optional; handy when consuming the plugin from another project locally
./gradlew test # Runs JVM tests for the plugin, runtime, and shared fixtures
Runtime behaviour is validated with Robolectric-based tests in deepmatch-processor/src/test, backed by reusable fakes from the deepmatch-testing module. The GitHub Action workflow (.github/workflows/ci.yml) runs the same test task on every push and pull request; enable branch protection to require the CI workflow before merging.