DeepLinkDispatch

repository·master·Indexed 26 days ago

https://github.com/airbnb/deeplinkdispatch

A declarative, annotation-based Android library for defining and dispatching deep links. It allows developers to map URIs to Activities or type-safe handlers using @DeepLink and @DeepLinkSpec annotations, reducing boilerplate. Features include automatic AndroidManifest.xml intent-filter generation via KSP, support for custom type conversion in DeepLinkDelegate, configurable path segment placeholders at runtime, and the ability to generate deep link documentation.

Tokens
6.1K
Snippets
16
Records
26
Agent score
82%

What's inside DeepLinkDispatch

  1. Publish a new Main release to Maven Central

    master

    To publish a new version of DeepLinkDispatch to Maven Central, follow these steps:

    1. Update the version in gradle.properties to a non-SNAPSHOT version (e.g., X.Y.Z).
    2. Commit the version change: git commit -am "Prepare for release X.Y.Z."
    3. Tag the release: git tag -a X.Y.Z -m "Version X.Y.Z"
    4. Configure Sonatype credentials (mavenCentralUsername and mavenCentralPassword) in your local user gradle.properties.
    5. Ensure a GPG signing key is configured.
    6. Execute the publish command: ./gradlew publishAllPublicationsToMavenCentral
    7. Revert gradle.properties to the next SNAPSHOT version.
    8. Commit the change: git commit -am "Prepare next development version."
    9. Push changes and tags: git push && git push --tags
    10. Merge to master and create a GitHub release.
  2. Install DeepLinkDispatch via Kapt

    master

    If your Kotlin project is already using Kapt, add the plugin and the required dependencies:

    1. Apply the plugin:
    plugins {
      id("kotlin-kapt")
    }
    1. Add the dependencies:
    dependencies {
      implementation 'com.airbnb:deeplinkdispatch:x.x.x'
      kapt 'com.airbnb:deeplinkdispatch-processor:x.x.x'
    }
    plugins {
      id("kotlin-kapt")
    }
    
    dependencies {
      implementation 'com.airbnb:deeplinkdispatch:x.x.x'
      kapt 'com.airbnb:deeplinkdispatch-processor:x.x.x'
    }
  3. Migrate from v4.x to v5.x

    master

    When upgrading to version 5.x, perform the following breaking changes:

    1. Rename Loader to Registry: The concept of a Loader has been renamed to Registry. Specifically, all generated *ModuleLoader classes are now *ModuleRegistry classes. You must update all code references to these classes.
    2. Handle Removed Classes: Several classes, such as com.airbnb.deeplinkdispatch.Parser, have been removed. If your code relies on these, you must find an alternative implementation.
    3. Update Interface for Core Classes: Some classes, such as com.airbnb.deeplinkdispatch.SchemeHostAndPath, have changed their interfaces. You must update your code to match the new method signatures or property access patterns.
  4. Configure path segment placeholders at runtime

    master

    Configurable path segment placeholders (e.g., <some_id>) allow you to change URL path elements at runtime without changing the library code. This is useful for libraries used across multiple apps with different URI structures.

    Usage:

    1. Define the placeholder in the URI: foo://cereal.com/<type_of_cereal>/nutritional_info.
    2. Provide a mapping in the DeepLinkDelegate constructor using a Map.

    Important:

    • You must provide a mapping for every placeholder used, or the app will crash at runtime.
    • To match an empty segment (effectively removing it), map the placeholder to an empty string "". Note that an empty placeholder cannot be the last element in the URL.
    @DeepLink("foo://cereal.com/<type_of_cereal>/nutritional_info")
    public static Intent intentForNutritionalDeepLinkMethod(Context context) {
      return new Intent(context, MainActivity.class)
          .setAction(ACTION_DEEP_LINK_METHOD);
    }
    
    // At runtime:
    Map configurablePlaceholdersMap = new HashMap();
    configurablePlaceholdersMap.put("type_of_cereal", "/obamaos");
    
    DeepLinkDelegate deepLinkDelegate = 
        new DeepLinkDelegate(new AppDeepLinkModuleRegistry(), new LibraryDeepLinkModuleRegistry(), configurablePlaceholdersMap);
  5. Publish a release to an internal Artifactory repository

    master

    To publish a release to an internal Artifactory repository, configure the following in your local gradle.properties:

    • ARTIFACTORY_USERNAME
    • ARTIFACTORY_PASSWORD
    • ARTIFACTORY_RELEASE_URL (and optionally ARTIFACTORY_SNAPSHOT_URL for snapshots)

    Run the following command to publish. You can use the -PdoNotSignRelease=true flag to skip GPG signing, which is useful for internal releases where signing is not required.

    ./gradlew publishAllPublicationsToAirbnbArtifactoryRepository -PdoNotSignRelease=true
  6. Enable automatic AndroidManifest.xml generation

    master

    DeepLinkDispatch can automatically generate intent-filter entries in your AndroidManifest.xml using ksp.

    Requirements:

    1. Must use ksp.
    2. Deep links must be in a module that is not an application module (i.e., not using com.android.application).
    3. You must specify activityClassFqn in the @DeepLink or @DeepLinkSpec annotation to reference the target Activity.

    Setup:

    1. Add the gradle plugin to your root build.gradle:
    buildscript {
        dependencies {
            classpath "com.airbnb:deeplinkdispatch-gradle-plugin:$VERSION"
        }
    }
    1. Apply the plugin in your module's build.gradle (must be applied after Kotlin and Android plugins):
    apply plugin: 'com.airbnb.deeplinkdispatch.manifest-generation'
    @DeepLink("http{scheme(|s)}://example.{domain(com|de|ro)}/deepLink/{id}", "{scheme(foo|bar)}://{host(example|another-example)}.{domain(com|de|ro)}/anotherDeepLink", activityClassFqn = "com.example.MainActivity")
    class MainActivity : Activity {
      @Override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        val intent : Intent = getIntent()
        if (intent.getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {
          val parameters : Bundle = intent.getExtras()
          val idString : String = parameters.getString("id")
          // Do something with idString
        }
      }
    }
  7. Test deep links using adb

    master

    You can test deep link dispatching using the Android Debug Bridge (adb). It is recommended to run adb shell first and then execute the am start command from within the shell to ensure URIs are parsed correctly.

    To fire a standard deep link (e.g., annotated with @DeepLink("dld://example.com/deepLink")): am start -W -a android.intent.action.VIEW -d "dld://example.com/deepLink" <YOUR_PACKAGE_NAME>

    To fire a deep link associated with a method that includes path parameters (e.g., annotated with @DeepLink("dld://methodDeepLink/{param1}")): am start -W -a android.intent.action.VIEW -d "dld://methodDeepLink/abc123" <YOUR_PACKAGE_NAME>

    To fire a deep link with multiple path segments (e.g., annotated with @DeepLink("http://example.com/deepLink/{id}/{name}")): am start -W -a android.intent.action.VIEW -d "http://example.com/deepLink/123abc/myname" <YOUR_PACKAGE_NAME>

  8. Migrate configurable path segments to V7.x

    master

    When upgrading to version 7.x, ensure that all replacements provided for configurable path segments start with a /.

    In previous versions, a replacement value of "" (empty string) might have been used to represent a segment, but in V7.x, "" is a valid value that will effectively remove the entire path segment from the resulting path. To preserve the segment structure, you must explicitly include the leading slash in your mapping.

    Example: If your path is testPath/<configurable-path-segment>/morePath, the mapping for configurable-path-segment must be /pathReplacement (resulting in testPath/pathReplacement/morePath) rather than pathReplacement.

  9. Listen for deep link events via Callbacks

    master

    You can register a BroadcastReceiver to listen for incoming deep links. DeepLinkDispatch uses LocalBroadcastManager to broadcast an Intent with the following extras:

    • DeepLinkHandler.EXTRA_URI: The URI of the deep link.
    • DeepLinkHandler.EXTRA_SUCCESSFUL: Whether the deep link was fired successfully.
    • DeepLinkHandler.EXTRA_ERROR_MESSAGE: The error message if the dispatch failed.
    public class DeepLinkReceiver extends BroadcastReceiver {
      @Override public void onReceive(Context context, Intent intent) {
        String deepLinkUri = intent.getStringExtra(DeepLinkHandler.EXTRA_URI);
        if (intent.getBooleanExtra(DeepLinkHandler.EXTRA_SUCCESSFUL, false)) {
          Log.i("TAG", "Success deep linking: " + deepLinkUri);
        } else {
          String errorMessage = intent.getStringExtra(DeepLinkHandler.EXTRA_ERROR_MESSAGE);
          Log.e("TAG", "Error deep linking: " + deepLinkUri + " with error message " + errorMessage);
        }
      }
    }
    
    // Register in Application class:
    LocalBroadcastManager.getInstance(this).registerReceiver(new DeepLinkReceiver(), new IntentFilter(DeepLinkHandler.ACTION));
  10. Implement DeepLinkHandler and Dispatching

    master

    To handle incoming deep links, you must provide your own Activity and annotate it with @DeepLinkHandler, passing the generated Registry classes as arguments.

    Inside onCreate, instantiate a DeepLinkDelegate with your module registries and call dispatchFrom(this). You should typically call finish() immediately after dispatching, as the delegate will start the target Activity.

    If you use configurable path segments, you can pass a Map of placeholders to the DeepLinkDelegate constructor.