Compartir a través de


Vínculos universales de Apple

A menudo es conveniente conectar un sitio web y una aplicación móvil para que los vínculos en un sitio web inicien la aplicación móvil y muestren contenido en la aplicación móvil. La vinculación de aplicaciones, también conocida como vinculación en profundidad, es una técnica que habilita un dispositivo móvil para responder a una URL e iniciar el contenido de una aplicación móvil representada por la URL.

En las plataformas de Apple, los vínculos profundos se conocen como vínculos universales. Cuando un usuario pulsa sobre un vínculo universal, el sistema lo redirige directamente a su aplicación sin enrutarlo a través de Safari o de su sitio web. Estos vínculos pueden basarse en un esquema personalizado, como myappname://, o pueden usar el esquema HTTP o HTTPS. Por ejemplo, al hacer clic en un vínculo de un sitio web de recetas se abriría una aplicación móvil asociada a ese sitio web, y después se mostraría una receta concreta al usuario. Los usuarios que no tienen instalada la aplicación se llevan al contenido de su sitio web. Este artículo se centra en vínculos universales que usan el esquema HTTPS.

Las aplicaciones de iOS de .NET MAUI admiten vínculos universales. Esto requiere hospedar un archivo JSON de vínculos de recursos digitales en el dominio, que describe la relación con la aplicación. Esto permite a Apple comprobar que la aplicación que intenta controlar una dirección URL tiene propiedad del dominio de direcciones URL para evitar que las aplicaciones malintencionadas intercepten los vínculos de la aplicación.

El proceso para controlar los vínculos universales de Apple en una aplicación .NET MAUI para iOS o Mac Catalyst es el siguiente:

Para más información, consulte Permitir que las aplicaciones y los sitios web vinculen a su contenido en developer.apple.com. Para obtener información sobre cómo definir un esquema de dirección URL personalizado para la aplicación, consulte Definición de un esquema de dirección URL personalizado para la aplicación en developer.apple.com.

Creación y hospedaje de un archivo de dominios asociados

Para asociar un sitio web a la aplicación, deberá hospedar un archivo de dominio asociado en su sitio web. El archivo de dominio asociado es un archivo JSON que se debe hospedar en el dominio en la siguiente ubicación: https://domain.name/.well-known/apple-app-site-association.

El siguiente JSON muestra el contenido de un archivo de dominios asociados típico:

{
    "activitycontinuation": {
        "apps": [ "85HMA3YHJX.com.companyname.myrecipeapp" ]
    },
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "85HMA3YHJX.com.companyname.myrecipeapp",
                "paths": [ "*", "/*" ]
            }
        ]
    }
}

Las claves apps y appID deben especificar los identificadores de las aplicaciones disponibles para usar en el sitio web. Los valores de estas claves se componen del prefijo del identificador de aplicación y del identificador de lote.

Importante

El archivo de dominio asociado debe hospedarse mediante https con un certificado válido y sin redireccionamientos.

Para más información, consulte Compatibilidad con dominios asociados en developer.apple.com.

Agregue a su aplicación el derecho de los dominios asociados

Después de hospedar un archivo de dominio asociado en el dominio, deberá agregar los derechos de dominios asociados a la aplicación. Cuando un usuario instala la aplicación, iOS intenta descargar el archivo de dominio asociado y comprobar los dominios de su derecho.

El derecho de dominios asociados especifica una lista de dominios a los que está asociada la aplicación. Este derecho debería agregarse al archivo Entitlements.plist de su aplicación. Para más información sobre cómo añadir un derecho en iOS, consulte Derechos. Para más información sobre cómo añadir un derecho en Mac Catalyst, consulte Derechos.

El derecho se define mediante la clave com.apple.developer.associated-domains, de tipo Array de String:

<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:recipe-app.com</string>
</array>

Para más información sobre este derecho, consulte Derecho de dominios asociados en developer.apple.com.

Como alternativa, puede modificar su archivo de proyecto (.csproj) para agregar el derecho en un elemento <ItemGroup>:

<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' Or $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">

    <!-- For debugging, use '?mode=developer' for debug to bypass apple's CDN cache -->
    <CustomEntitlements
        Condition="$(Configuration) == 'Debug'"
        Include="com.apple.developer.associated-domains"
        Type="StringArray"
        Value="applinks:recipe-app.com?mode=developer" />

    <!-- Non-debugging, use normal applinks:url value -->
    <CustomEntitlements
        Condition="$(Configuration) != 'Debug'"
        Include="com.apple.developer.associated-domains"
        Type="StringArray"
        Value="applinks:recipe-app.com" />

</ItemGroup>

En este ejemplo, sustituya el applinks:recipe-app.com por el valor correcto para su dominio. Asegúrese de incluir solo el subdominio deseado y el dominio de nivel superior. No incluya componentes de ruta de acceso y consulta ni una barra oblicua final (/).

Nota:

En iOS 14+ y macOS 11+, las aplicaciones ya no envían solicitudes de archivos apple-app-site-association directamente a su servidor web. En su lugar, envían solicitudes a una red de entrega de contenido (CDN) administrada por Apple dedicada a dominios asociados.

Adición de la funcionalidad de dominios asociados al identificador de aplicación

Después de agregar el derecho de dominios asociados a la aplicación, deberá agregar la funcionalidad de dominios asociados al identificador de aplicación de la aplicación en la cuenta de Apple Developer. Esto es necesario porque los derechos definidos en la aplicación también deben agregarse como funcionalidades al identificador de aplicación de la aplicación en la cuenta de Apple Developer.

Para agregar la funcionalidad de dominios asociados al identificador de aplicación, siga estos pasos:

  1. En un explorador web, inicie sesión en su cuenta Apple Developer y vaya a la página Certificates, IDs & Profiles.

  2. En la página Certificates, IDs & Profiles, seleccione la pestaña Identifiers.

  3. En la página Identifiers, seleccione el identificador de aplicación correspondiente a la aplicación.

  4. En la página Edit your App ID Configuration del identificador de aplicación, habilite la funcionalidad Associated Domains y, luego, haga clic en el botón Save:

    Screenshot of enabling the associated domains capability in the Apple Developer Portal.

  5. En el cuadro de diálogo Modify App Capabilities, haga clic en el botón Confirm.

Después de actualizar el identificador de aplicación de la aplicación, deberá generar y descargar un perfil de aprovisionamiento actualizado.

Nota:

Si posteriormente elimina los derechos de dominios asociados de la aplicación, deberá actualizar la configuración del identificador de aplicación de su cuenta de Apple Developer.

Cuando un usuario activa un vínculo universal, iOS y Mac Catalyst inician su aplicación y le envían un objeto NSUserActivity. Este objeto se puede consultar para determinar cómo se inició la aplicación y determinar qué acción realizar. Esto debería estar realizándose en los delegados del ciclo de vida de FinishedLaunching y ContinueUserActivity. El delegado de FinishedLaunching se invoca cuando la aplicación se ha iniciado, y el de ContinueUserActivity cuando la aplicación está en ejecución o suspendida. Para más información sobre los delegados del ciclo de vida, consulte Eventos del ciclo de vida de la plataforma.

Para responder a un delegado de ciclo de vida de iOS que se invoca, llama al método ConfigureLifecycleEvents en el objeto MauiAppBuilder del método MauiProgram de la clase CreateMauiapp. Después, en el objeto ILifecycleBuilder, llame al método AddiOS y especifique el Action que registra un controlador para el delegado requerido:

using Microsoft.Maui.LifecycleEvents;
using Microsoft.Extensions.Logging;

namespace MyNamespace;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureLifecycleEvents(lifecycle =>
            {
#if IOS || MACCATALYST
                lifecycle.AddiOS(ios =>
                {
                    // Universal link delivered to FinishedLaunching after app launch.
                    ios.FinishedLaunching((app, data) => HandleAppLink(app.UserActivity));

                    // Universal link delivered to ContinueUserActivity when the app is running or suspended.
                    ios.ContinueUserActivity((app, userActivity, handler) => HandleAppLink(userActivity));

                    // Only required if using Scenes for multi-window support.
                    if (OperatingSystem.IsIOSVersionAtLeast(13) || OperatingSystem.IsMacCatalystVersionAtLeast(13))
                    {
                        // Universal link delivered to SceneWillConnect after app launch
                        ios.SceneWillConnect((scene, sceneSession, sceneConnectionOptions)
                            => HandleAppLink(sceneConnectionOptions.UserActivities.ToArray()
                                .FirstOrDefault(a => a.ActivityType == Foundation.NSUserActivityType.BrowsingWeb)));

                        // Universal link delivered to SceneContinueUserActivity when the app is running or suspended
                        ios.SceneContinueUserActivity((scene, userActivity) => HandleAppLink(userActivity));
                    }
                });
#endif
            });

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }

#if IOS || MACCATALYST
    static bool HandleAppLink(Foundation.NSUserActivity? userActivity)
    {
        if (userActivity is not null && userActivity.ActivityType == Foundation.NSUserActivityType.BrowsingWeb && userActivity.WebPageUrl is not null)
        {
            HandleAppLink(userActivity.WebPageUrl.ToString());
            return true;
        }
        return false;
    }
#endif

    static void HandleAppLink(string url)
    {
        if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out var uri))
            App.Current?.SendOnAppLinkRequestReceived(uri);
    }
}

Cuando iOS abra su aplicación como resultado de un vínculo universal, el objeto NSUserActivity tendrá una propiedad ActivityType con un valor de BrowsingWeb. La propiedad WebPageUrl del objeto de actividad contendrá la URL a la que quiere acceder el usuario. La dirección URL puede pasarse a su clase App con el método SendOnAppLinkRequestReceived.

Nota:

Si no está usando Escenas en su aplicación para la compatibilidad con múltiples ventanas, puede omitir los controladores del ciclo de vida para los métodos de Escena.

En la clase App, invalide el método OnAppLinkRequestReceived para recibir y procesar la URL:

namespace MyNamespace;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }

    protected override async void OnAppLinkRequestReceived(Uri uri)
    {
        base.OnAppLinkRequestReceived(uri);

        // Show an alert to test that the app link was received.
        await Dispatcher.DispatchAsync(async () =>
        {
            await Windows[0].Page!.DisplayAlert("App link received", uri.ToString(), "OK");
        });

        Console.WriteLine("App link: " + uri.ToString());
    }
}

En el ejemplo anterior, la invalidación de OnAppLinkRequestReceived muestra la URL del vínculo de la aplicación. En la práctica, el vínculo de la aplicación debe llevar a los usuarios directamente al contenido representado por la URL, sin solicitudes, inicios de sesión u otras interrupciones. Por lo tanto, la invalidación de OnAppLinkRequestReceived es la ubicación desde la que se invoca la navegación hacia el contenido representado por la URL.

Advertencia

Los vínculos universales ofrecen un vector de ataque potencial a su aplicación, por lo que debe asegurarse de validar todos los parámetros de la URL y descartar cualquier URL malformada.

Para más información, consulte Compatibilidad de los vínculos universales en su aplicación en developer.apple.com.

Importante

En iOS, los vínculos universales deben probarse en un dispositivo en lugar de en un simulador.

Para probar un vínculo universal, pegue un vínculo en la aplicación Notas y manténgalo pulsado (en iOS) o pulse Control y haga clic en él (en macOS) para descubrir sus opciones para seguir el vínculo. Siempre que los vínculos universales se hayan configurado correctamente, aparecerá la opción de abrir en la aplicación y en Safari. Su elección establecerá el comportamiento predeterminado en el dispositivo cuando siga los vínculos universales de este dominio. Para cambiar esta opción predeterminada, repita los pasos y realice otra opción.

Nota:

Al escribir la dirección URL en Safari, nunca se abrirá la aplicación. En su lugar, Safari aceptará esta acción como navegación directa. Siempre que un usuario esté en el dominio después de navegar allí directamente, el sitio mostrará un banner para abrir la aplicación.

En iOS, puede probar los vínculos universales con las pruebas de diagnóstico de dominios asociados en la configuración del desarrollador:

  1. Habilite el modo de desarrollador en Configuración. Para más información, consulte Habilitar el modo de desarrollador en un dispositivo en developer.apple.com.
  2. En Configuración> Desarrollador, desplácese hasta Vínculos universales y habilite Desarrollo de dominios asociados.
  3. Abra Diagnósticos y escriba la dirección URL. A continuación, recibirá comentarios sobre si el vínculo es válido para una aplicación instalada.

A menudo, los vínculos universales no válidos son el resultado de una configuración incorrecta de applinks.

Para ver consejos sobre cómo solucionar problemas, consulte Depuración de vínculos universales en developer.apple.com.