La solución Deeplink para aplicaciones IOS y Android funciona en Facebook

Hay demasiados tutoriales de enlaces profundos (enlaces universales o enlaces de aplicaciones). Pero la mayoría de ellos muestra cómo habilitarlo en aplicaciones Android o IOS. También hay soluciones de pago en la nube, pero ofrecen muchas funciones. Pero hay tres problemas principales que enfrenté en la vida real:

Algunos navegadores no permiten que funcionen los enlaces de aplicaciones. Por ejemplo, puede configurar http://example.com para que quede atrapado en la aplicación, pero si el usuario hace clic en este enlace a través de la aplicación de Facebook, no se maneja y el navegador de Facebook muestra el sitio web.No existe una solución estándar única para manejar enlaces tanto para aplicaciones Android como IOS.No hay una solución práctica si la aplicación no está instalada en un dispositivo móvil y el usuario hace clic en un enlace de aplicación.

Escribí este Q&A que es el resultado de mis estudios (pasé demasiadas horas) para tener una solución única y funcional para todos los casos.

Los códigos provienen de mi solución de trabajo, pero eliminé algunas partes solo para mostrar la idea. Si hay algunos problemas de compilación, siga el algoritmo y escriba su propio código

Aquí está la solución, vaya paso a paso incluso si conoce algunos pasos, porque hay trucos en los códigos. También hay algunas explicaciones en las líneas de comentarios de las partes del código, léalas.

Los ejemplos son manejar enlaces profundos http://example.com/v/ por sus aplicaciones Android e IOS con un argumento al final, por ejemplo http://example.com/v/id-of-user?key=value.

1. Configurando Android

1.1 Agregue información de actividad a su archivo AndroidManifest.xml:

<activity
android:name=".appLinkHandlerActivity">

<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:host="example.com"
        android:pathPrefix="/v/"
        android:scheme="http" />
</intent-filter>

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

<!—this intent is needed to handle links to myapp://share, I will explain later why we need it -->
    <data
        android:host="share"
        android:scheme="myapp" />
</intent-filter>

1.2 Cree una actividad llamada appLinkHandlerActivity que manejará los enlaces en los que se hizo clic

    public class appLinkHandlerActivity extends AppCompatActivity {


    /* assume that user is clicked http://example.com/v/my-user-id   
    actCode will be “v”, pCode will be “my-user-id” */
    String actCode="", pCode="";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        // ATTENTION: This was auto-generated to handle app links.
        Intent appLinkIntent = getIntent();
        String appLinkAction = appLinkIntent.getAction();
        Uri appLinkData = appLinkIntent.getData();



        String code = null;
        try {
            code = getIntent().getData().getLastPathSegment();
        } catch (Exception e) {

        }

        if (code == null) {
            Intent i = new Intent(this, {your main activity.class});
            startActivity(i);
        }

        List<String> params=appLinkData.getPathSegments();


        if (params.size()>0)
            actCode=params.get(0);

        if (params.size()>=2)
            pCode=params.get(1);

        /* assume that user is clicked http://example.com/v/my-user-id actCode is “v”, pCode is “my-user-id”  Do now whatever you need. */
    } 
 }

2. Configurando IOS

Esto es más complejo que Android, explicaré los puntos necesarios aquí. Por favor refiérase a los documentos:https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW1

https://www.raywenderlich.com/128948/universal-links-make-connection

2.1 Debe habilitar los dominios asociados al crear un ID de aplicación en el Portal de desarrolladores de Apple. Problema importante: debe tener una cuenta de desarrollador Apple comprada para habilitar esta opción, es decir, sin comprar una cuenta de desarrollador, no puede probar AppLinks en su proyecto IOS.

2.2 En el proyecto XCode, abra la pestaña "Capacidades" y cambie Dominios asociados a Activado. Si no habilitó los dominios asociados en la sección de ID de la aplicación del portal de desarrolladores de Apple, es posible que no se pueda seleccionar Agregue un derecho haciendo clic en el botón + en la opción Dominios asociados, escriba "applinks: example.com".

2.3 Cree un archivo en su servidor web llamado "apple-app-site-association" y se debe acceder a este archivo a través de https://example.com/apple-app-site-association HTTPS es obligatorio y si no es válido El certificado SSL App Link podría no funcionar. Agregue las siguientes líneas en el archivo apple-app-site-association:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "6HY7TF56.com.example.app",
                "paths": [ "/ios/*", "/v/*" ]
            }
        ]
    }
}

appID es el formato de {"ID del equipo". "ID del paquete de su aplicación"}. Puede encontrar su ID de equipo en la sección Detalles de membresía en el Portal del desarrollador.

Manejamos el enlace http://example.com/v/parameters, pero aquí puede ver que hay otra configuración de ruta para "/ ios / *". Es necesario evitar los navegadores no compatibles, explicaré más adelante.

2.4 En el archivo AppDelegate.m agregue dos métodos para manejar los clics del usuario en example.com

-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
    if ([userActivity.activityType isEqualToString: NSUserActivityTypeBrowsingWeb]) {

        NSURL *url = userActivity.webpageURL;
          [self parseUrl:url];

    }
return YES;
}


- (void) parseUrl:(NSURL * )handledUrl {
    NSString *urlStr=@"";
    NSString *pCode=@"";
    NSString *handledUrlStr=[handledUrl parameterString];

    NSString *handledUrlQueryPart;

    NSArray<NSString *> *pathsArray= [handledUrl pathComponents];

    //remember that we only added paths “/v/*” and “/ios/*” to handle in apple-app-site-association file. If you want to handle more subpaths you can add them into apple-app-site-association file, then below if-else conditions. Don’t touch to config and code for “/ios/*” path, it is needed to bypass unsopported browsers.
    if ([pathsArray[1]  isEqual: @"v"]){
        //sample url= http://example.com/v/menu?aaa=bbb
        pCode = pathsArray[2];
        handledUrlQueryPart=[handledUrl query];
    } else if ([pathsArray[1]  isEqual: @"ios"]){
        //sample url= http://example.com/ios/deeplink-ios.php?/v/menu?aaa=bbb
        NSArray *uriArray = [[handledUrl query] componentsSeparatedByString:@"?"];
           NSArray *queryPathsArray = [uriArray[0] componentsSeparatedByString:@"/"];
        if ([queryPathsArray count] > 2)
            pCode = queryPathsArray[2];

        if ([uriArray count] > 1 ){
            handledUrlQueryPart=uriArray[1];
        }
    }

    /* here pCode is the parameter what is passed from user. If the link clicked is http://example.com/v/menu it is “menu”. If the link clicked is http://example.com/v/menu?aaa=bbb it is “menu?aaa=bbb”. So you can do now what ever you need. */    
}

3. Gestionar los clics no capturados.

3.1 Ok, sus aplicaciones de Android e IOS deben manejar los clics en el enlace http://example.com/v/blabla y pasar el parámetro "blabla" a la variable pCode utilizada en los métodos que mostré. Pero algunas cejas, como la aplicación de Facebook, pueden deshabilitar los enlaces de aplicaciones para que funcionen. En este caso, el clic del usuario va a su servidor web y el navegador intenta mostrar el contenido de http://example.com/v/blabla, que probablemente sea 404 Page Not Found. Para manejar estos clics, configuraremos el servidor web Apache y redirigiremos a los usuarios a su aplicación. Si usa IIS u otro, no sé cómo hacerlo, pero puede tomar esto como muestra y usar el mismo algoritmo para configurar su servidor web.

3.2 Escriba las siguientes líneas en el archivo .htaccess en el directorio raíz de example.com

#redirect to deeplink
<IfModule mod_rewrite.c>

#if there is a request to example.com/v/any-sub-path, redirect them to example.com/deeplink.php file. This rule is for both IOS and Android
RewriteRule ^(v)/.* /deeplink.php [L]

#if there is a request to example.com/ios/any-sub-path, redirect them to app installation page. That means your app is not installed on IOS device. This rule is for IOS devices only
RewriteRule ^(ios)/.* http://itunes.apple.com/install-of-your-app [L] 
</IfModule>  

4. Redireccionar usuarios a aplicaciones

4.1 Las reglas de redirección en el archivo .htaccess que se muestran en el paso 3 redirigen a los usuarios al archivo deeplink.php. Así que aquí está el contenido de ese archivo para redirigir a los usuarios a su aplicación.

 <?php

$request_uri=$_SERVER[REQUEST_URI];

$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
if(stripos($ua,'android') == true){
//if user device is android, redirect it to intent url which is handled by Android.
        $redir_tag="<meta http-equiv='refresh' content='0;url=intent://share$request_uri/#Intent;scheme=myapp;S.browser_fallback_url=http%3A%2F%2Fexample.com%2Fget-app%2F;package=com.example.app;end' />";
//scheme=myapp and host named “share” is configured in AndroidManifest.xml file to be handled by the activity.
//fallback url is the url, if your app is not installed on android device, so you can redirect them to a page to install android app. In some cases users are redirected to Play Store directly for application id of com.example.app
}

else if ( (stripos($ua,'iPhone') == true) || (stripos($ua,'iPad') == true) ) {
        //if user device is IOS, redirect them to a web page to see. There will be a link here to the another handled link: http://example.com/ios/blabla.
        // due to my experience there is no way to redirect IOS to app directly at this stage, user must click a link on browser and that link must be different than the link which was shown and clicked at first.
        // another experience taught me ther ecan be problems if we redirect users to a web page under example.com which is configured as applink, so I redirect users to a page under deep.example.com here
        $redir_tag="<meta http-equiv='refresh' content='0;url=http://deep.example.com/deeplink-ios.php?$request_uri' />";
}

else {
//If the device is neither IOS nor Android, redirect users to a web page which gives information that this link is for Android and IOS only
        $redir_tag="<meta http-equiv='refresh' content='0;url=http://example.com/non-mobile' />";
}


?>



<html>
    <head>

        <!— add tags for no-caching, this is important, the date below is my son’s birth time and date, he is now 6, so you can use it as a date in the past -->
        <meta http-equiv="cache-control" content="max-age=0" />
        <meta http-equiv="cache-control" content="no-cache" />
        <meta http-equiv="expires" content="-1" />
        <meta http-equiv="expires" content="Tue, 31 May 2011 10:15:00 GMT+3" />
        <meta http-equiv="pragma" content="no-cache" />


        <?php echo $redir_tag; ?>

    </head>
</html>

5. Muestre a los usuarios de IOS un enlace para hacer clic

5.1 Aquí está el contenido del archivo http://deep.example.com/deeplink-ios.php. Los usuarios verán una página como la siguiente, cuando hagan clic en el enlace, esa solicitud debe ser manejada por su aplicación IOS.

<?php
//we create a link to http://example.com/ios/… which is configure to be handled by IOS app. IOS needs to be a user click in some cases to handle the request, that is why this page is shown to the user
$request_uri=$_SERVER[REQUEST_URI];
$link="<div class='w3-container w3-card'><h1><a href='http://example.com/ios$request_uri'>Click here to open MyApp</a></h1></div>";
?>

<html>
    <head>

        <!—adding no-cache tags is also important here-->
        <meta http-equiv="cache-control" content="max-age=0" />
        <meta http-equiv="cache-control" content="no-cache" />
        <meta http-equiv="expires" content="-1" />
        <meta http-equiv="expires" content="Tue, 31 May 2011 10:15:00 GMT+3" />
        <meta http-equiv="pragma" content="no-cache" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3mobile.css">

    </head>
<body>

<?php echo $link ?>

</body>
</html>

6. Análisis de casos:

6.1 Android

6.1.1 Caso 1: la aplicación está instalada en el dispositivo
• Solicitudes del navegador para http://example.com/v/blabla
• Android captura el enlace y crea la actividad configurada en su archivo de manifiesto

6.1.2 Caso 2: la aplicación está instalada en el dispositivo
• Solicitudes del navegador para http://example.com/v/blabla
• Android no puede atrapar el enlace.
• El navegador se conecta al servidor web, solicite / v / blabla
• Se redirige a deeplink.php? / V / blabla debido a la configuración en el archivo .htaccess
• deeplink.php se entera de que es Android y lo redirige a: intent: // share / v / blabla / # Intent; esquema = myapp; S.browser_fallback_url = http% 3A% 2F% 2Fexample.com% 2Fget-app% 2F; paquete = com.example.app
• Android detecta la solicitud que es para intento: //, por lo que debido a la configuración en el archivo de manifiesto myapp: // share / v / blabla es manejada por la actividad

6.1.3 Caso 3 - la aplicación no está instalada
• Solicitudes del navegador para http://example.com/v/blabla
• Android no puede atrapar el enlace.
• El navegador se conecta al servidor web, solicite / v / blabla
• Se redirige a deeplink.php? / V / blabla debido a la configuración en el archivo .htaccess
• deeplink.php se entera de que es Android y lo redirige a: intent: // share / v / blabla / # Intent; esquema = myapp; S.browser_fallback_url = http% 3A% 2F% 2Fexample.com% 2Fget-app% 2F; paquete = com.example.app
• Android detecta la solicitud que es para intent: //, pero no hay una aplicación instalada para id: com.example.app. Falbacks y redirige el navegador a http://example.com/get-app o la página de instalación de Play Store de tu aplicación en algunos casos

6.2 IOS

6.2.1 Caso 1: la aplicación está instalada en el dispositivo
• Solicitudes del navegador para http://example.com/v/blabla
• IOS captura el enlace y llama al método continueUserActivity en AppDelegate.m

6.2.2 Caso 2: la aplicación está instalada en el dispositivo
• Solicitudes del navegador para http://example.com/v/blabla
• IOS no puede atrapar el enlace.
• El navegador se conecta al servidor web, solicite / v / blabla
• Se redirige a deeplink.php? / V / blabla debido a la configuración en el archivo .htaccess
• deeplink.php descubre que es IOS y lo redirige a: http://deep.example.com/deeplink-ios.php?/v/blabla
• El archivo deeplink-ios.php muestra una URL al usuario. La URL es: http://lify.me/ios/v/blabla
• El usuario hace clic en la URL y el navegador solicita http://lify.me/ios/v/blabla
• IOS detecta la solicitud debido a la configuración de la ruta “/ ios / *” en el archivo de asociación de sitio de la aplicación apple y llama al método continueUserActivity en AppDelegate.m
• Si IOS no puede atender la solicitud de http://lify.me/ios/v/blabla por algún motivo, se comportará ya que la aplicación no está instalada en el dispositivo. Ver ese caso.

6.2.3 Caso 2: la aplicación no está instalada en el dispositivo
• Solicitudes del navegador para http://example.com/v/blabla
• IOS no puede atrapar el enlace.
• El navegador se conecta al servidor web, solicite / v / blabla
• Se redirige a deeplink.php? / V / blabla debido a la configuración en el archivo .htaccess
• deeplink.php descubre que es IOS y lo redirige a: http://deep.example.com/deeplink-ios.php?/v/blabla
• El archivo deeplink-ios.php muestra una URL al usuario. La URL es: http://lify.me/ios/v/blabla
• El usuario hace clic en la URL y el navegador solicita http://lify.me/ios/v/blabla
• Si IOS no puede atrapar la solicitud de http://lify.me/ios/v/blabla
• El navegador se conecta al servidor web, solicite / ios / v / blabla
• Se redirige a http://itunes.apple.com/install-of-your-app debido a la configuración en el archivo .htaccess en el servidor web

6.3 Se hace clic en App Link en un dispositivo que no sea Android o IOS
• Solicitudes del navegador para http://example.com/v/blabla
• El sistema operativo del dispositivo no puede atrapar el enlace.
• El navegador se conecta al servidor web, solicite / v / blabla
• Se redirige a deeplink.php? / V / blabla debido a la configuración en el archivo .htaccess
• deeplink.php descubre que no es ni iOS ni Android, y lo redirige a: http://example.com/non-mobile

Respuestas a la pregunta(0)

Su respuesta a la pregunta