Skip to content

Add Universal Links support to the iOS API library #3

@biodranik

Description

@biodranik

Summary

OMApi (Obj-C) and OrganicMaps (Swift) currently round-trip data through custom URL schemes (OMApiExampleCapitals://pin?…). Every time Organic Maps hands control back, iOS shows an "Open in ?" confirmation dialog. Universal Links (https://yourdomain.com/…) would skip that dialog and feel native. The library has no support for them today.

This is an additive enhancement — custom URL schemes should remain supported for small/hobbyist callers without their own domain.

Current state

  • +[OMApi detectBackUrlScheme] (and the Swift equivalent) reads the first CFBundleURLScheme from CFBundleURLTypes and passes it as backurl=.
  • Callbacks arrive in application(_:open:options:) and are parsed by +[OMApi pinFromUrl:] / OrganicMaps.pin(from:).

Universal Links use a different delegate hook (application(_:continue:restorationHandler:) with NSUserActivity of type NSUserActivityTypeBrowsingWeb) and a different discovery mechanism (applinks: entitlement + apple-app-site-association file).

Required changes

Library API additions

Obj-C:

@interface OMApi (UniversalLinks)
/// Opt-in universal-link prefix. Example: @"https://example.com/om-callback".
/// When set, this is passed as `backurl=` instead of the auto-detected custom scheme.
+ (void)setCallbackUniversalLinkPrefix:(nullable NSString *)urlPrefix;
+ (nullable OMPin *)pinFromUserActivity:(nonnull NSUserActivity *)userActivity;
@end

Swift:

extension OrganicMaps {
  /// Opt-in universal-link prefix; nil → fall back to custom URL scheme.
  static var callbackUniversalLinkPrefix: String? { get set }
  static func pin(from userActivity: NSUserActivity) -> OMPin?
}

When callbackUniversalLinkPrefix is set, backurl=https://example.com/om-callback is sent to Organic Maps. When unset, behaviour is identical to today.

Documentation

The README needs a new section explaining:

  1. Caller must add com.apple.developer.associated-domains entitlement with applinks:example.com.
  2. Caller must serve a valid AASA file at https://example.com/.well-known/apple-app-site-association with the right team-prefixed app ID.
  3. iOS's failure mode is "open the URL in Safari", so the page at the callback prefix should at minimum redirect to the App Store listing for the calling app.
  4. The custom URL scheme path remains the default for callers without a domain.

Example app

Add a third example, or a build flag in the existing one, that demonstrates the universal-link flow.

Dependency on Organic Maps

A small change is required on the Organic Maps iOS side for HTTPS callbacks to actually go to the caller's app instead of Safari: MapViewController.goBack (iphone/Maps/UI/Map/MapViewController.mm:1068-1073) currently calls openURL:options:@{} — needs to pass UIApplicationOpenURLOptionUniversalLinksOnly: @YES with a fallback when routing fails.

Filed separately on organicmaps/organicmaps if needed (covered as part of the API round-trip issue: organicmaps/organicmaps#12802).

Why bother

  • No "Open in ?" system dialog on the return trip — matches the friction-free MAPS.ME-era UX.
  • Custom URL schemes are increasingly restricted on iOS (declared queries, prompts on openURL); Universal Links are Apple's recommended approach for app-to-app handoff.

Out of scope

  • Removing custom URL scheme support. Many callers don't have a domain — the two should coexist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions