¿Es posible registrar un esquema de URL basado en dominio http + para aplicaciones de iPhone, como YouTube y Maps?

223

Me gustaría tener iOS para abrir las URL de mi dominio (por ejemplo, http://martijnthe.nl ) con mi aplicación cada vez que la aplicación esté instalada en el teléfono y con Mobile Safari en caso de que no lo esté.

Leí que es posible crear un sufijo de protocolo único para esto y registrarlo en Info.plist, pero Mobile Safari dará un error en caso de que la aplicación no esté instalada.

¿Cuál sería una solución alternativa?

Una idea:

1) Use http: // URL que se abren en cualquier navegador de escritorio y prestan el servicio a través del navegador

2) Verifique el User-Agent y, en caso de que sea Mobile Safari, abra myprotocol: // URL para (intentar) abrir la aplicación de iPhone y haga que abra Mobile iTunes para descargar la aplicación en caso de que el intento falle

No estoy seguro si esto funcionará ... ¿sugerencias? ¡Gracias!

Martijn Thé
fuente
44
En el metro de Nueva York, hay wifi de Boingo que le brinda acceso gratuito a WiFi si descarga una aplicación que le recomiendan. Una vez que lo descargas, vuelves a Safari y el navegador detecta si estaba instalado y luego te otorga acceso. ¿Alguna idea de cómo se está haciendo eso?
TommyG
2
Universal Links ahora admitiría este caso de uso sin ningún mensaje de error. Aquí le mostramos cómo configurar su dominio y aplicación: blog.branch.io/…
Alex Austin

Respuestas:

243

Creo que la forma menos intrusiva de hacer esto es la siguiente:

  1. Compruebe si el agente de usuario es el de un iPhone / iPod Touch
  2. Comprueba si hay una appInstalledcookie
  3. Si la cookie existe y está establecida en verdadera, configúrela window.locationen your-uri://(o realice el redireccionamiento del lado del servidor)
  4. Si la cookie no existe, abra un "¿Sabía que el nombre de su sitio tiene una aplicación para iPhone?" modal con un "Sí, ya lo tengo", "No, pero me encantaría probarlo" y el botón "Déjame en paz".
    1. El botón "Sí" establece la cookie en verdadera y redirige a your-uri://
    2. El botón "No" redirige a " http://itunes.com/apps/yourappname " que abrirá la App Store en el dispositivo
    3. El botón "Déjame en paz" establece la cookie en falso y cierra el modal

La otra opción con la que jugué pero que encontré un poco torpe fue hacer lo siguiente en Javascript:

setTimeout(function() {
  window.location = "http://itunes.com/apps/yourappname";
}, 25);

// If "custom-uri://" is registered the app will launch immediately and your
// timer won't fire. If it's not set, you'll get an ugly "Cannot Open Page"
// dialogue prior to the App Store application launching
window.location = "custom-uri://";
Nathan de Vries
fuente
16
Gran solución Si su respaldo es a otra aplicación, se cargará INMEDIATAMENTE sin mostrar el error. Entonces, en lugar de recurrir a itunes.com ... use itms: //phobos.apple.com / ... para evitar el error emergente.
jb.
47
Problema : cuando window.location="custom-uri://tiene éxito, no se elimina el tiempo de espera de reserva. Cuando el usuario regrese al navegador desde su aplicación, el temporizador aún estará allí e iniciará el enlace de la tienda de aplicaciones. Esta es una experiencia de usuario deficiente.
JoJo
55
Parece que las Cookies están en el espacio aislado en # ios6, por lo que no puede acceder a las cookies configuradas por una aplicación desde otra. (App WebUI y Safari Mobile, por ejemplo)
Olivier Amblet
2
¿Alguien encuentra una manera de evitar que el tiempo de espera original se active cuando el usuario vuelve al navegador? (el problema votado que JoJo menciona)
cobolstinks
2
Para resolver el problema que menciona JoJo, solo ejecute el código en el tiempo de espera si no ha pasado "mucho tiempo" desde que el usuario hizo clic en el enlace. Vea esta solución: stackoverflow.com/a/14751543/533420
kkara
95

Es muy posible hacer esto en JavaScript, siempre y cuando su reserva sea otra aplicación adicional. Sobre la base de la sugerencia de Nathan :

<html>
  <head>
    <meta name="viewport" content="width=device-width" />
  </head>
  <body>

    <h2><a id="applink1" href="fb://profile/116201417">open facebook with fallback to appstore</a></h2>
    <h2><a id="applink2" href="unknown://nowhere">open unknown with fallback to appstore</a></h2>
    <p><i>Only works on iPhone!</i></p>    

  <script type="text/javascript">

// To avoid the "protocol not supported" alert, fail must open another app.
var appstorefail = "itms://itunes.apple.com/us/app/facebook/id284882215?mt=8&uo=6";

function applink(fail){
    return function(){
        var clickedAt = +new Date;
        // During tests on 3g/3gs this timeout fires immediately if less than 500ms.
        setTimeout(function(){
            // To avoid failing on return to MobileSafari, ensure freshness!
            if (+new Date - clickedAt < 2000){
                window.location = fail;
            }
        }, 500);    
    };
}

document.getElementById("applink1").onclick = applink(appstorefail);
document.getElementById("applink2").onclick = applink(appstorefail);

</script>
</body>
</html>

Mira una demostración en vivo aquí .

jb.
fuente
77
De acuerdo con Lee, esta parece una solución más sencilla, aunque todavía recibo el mensaje de error de safari si la aplicación no existe y se redirige a la tienda de aplicaciones.
Jon
2
Usé esta solución tanto para Android como para iOS. Descubrí que si cambio el valor del tiempo de espera de 500 a 100, no aparece el cuadro de diálogo emergente "No se puede abrir la página" en iOS. También descubrí que el tiempo de espera debe ser 50 para Android
Rossini
14
El uso de "itms-apps:" en lugar de "itms:" guarda 1 redirección y abre directamente la página de la aplicación en la tienda de aplicaciones.
Alemán Latorre
66
@Rossini está integrado en Android configurando un filtro de intención para su acción que responde a un host en particular
jwadsack
99
¿Alguien sabe cómo evitar el mensaje de error "no se puede abrir la página" de safari si la aplicación no está instalada y antes de redirigir a la tienda de aplicaciones?
davidk
26

Para dispositivos iOS 6, hay una opción: Promover aplicaciones con Smart App Banners

Oh ho
fuente
12
Lamentablemente, el banner de aplicaciones inteligentes solo es compatible con Mobile Safari, no con UIWebviewComponent. Por lo tanto, no se mostrará si su sitio se muestra dentro de un cliente de Twitter, por ejemplo.
Olivier Amblet
24

Descubrí que la respuesta seleccionada funciona para las aplicaciones del navegador, pero estaba teniendo problemas con el código que funciona en aplicaciones que no son del navegador que implementan a UIWebView.

El problema para mí era que un usuario en la aplicación de Twitter haría clic en un enlace que los llevaría a mi sitio a través de un UIWebViewen la aplicación de Twitter. Luego, cuando hicieron clic en un botón de mi sitio, Twitter intenta ser elegante y solo completa el window.locationsi el sitio es accesible. Entonces, lo que sucede es una UIAlertViewventana emergente que dice si está seguro de que desea continuar y luego redirige inmediatamente a la App Store sin una segunda ventana emergente.

Mi solución involucra iframes. Esto evita que UIAlertViewse presente, lo que permite una experiencia de usuario simple y elegante.

jQuery

var redirect = function (location) {
    $('body').append($('<iframe></iframe>').attr('src', location).css({
        width: 1,
        height: 1,
        position: 'absolute',
        top: 0,
        left: 0
    }));
};

setTimeout(function () {
    redirect('http://itunes.apple.com/app/id');
}, 25);

redirect('custom-uri://');

Javascript

var redirect = function (location) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('src', location);
    iframe.setAttribute('width', '1px');
    iframe.setAttribute('height', '1px');
    iframe.setAttribute('position', 'absolute');
    iframe.setAttribute('top', '0');
    iframe.setAttribute('left', '0');
    document.documentElement.appendChild(iframe);
    iframe.parentNode.removeChild(iframe);
    iframe = null;
};

setTimeout(function () {
    redirect('http://itunes.apple.com/app/id');
}, 25);

redirect('custom-uri://');

EDITAR:

Agregue la posición absoluta al iframe para que cuando se inserte no haya un espacio en blanco al azar en la parte inferior de la página.

También es importante tener en cuenta que no he encontrado la necesidad de este enfoque con Android. Usar window.location.hrefdebería funcionar bien.

cnotethegr8
fuente
1
¡¡Funciona!! Gracias, finalmente encontré una solución que funciona en todos los navegadores.
koleror
2
Esta es la mejor solución si se encuentra. Gracias. Ya no hay error emergente.
Confile
1
@Tim si desea que este código se active cuando se hace clic en un enlace, entonces envuelva este código en una función que se llama una vez que se hace clic en el enlace.
cnotethegr8
1
@ cnotethegr8 Lo he puesto en una función y redirigir a una URL personalizada funciona muy bien, pero el retroceso a iTunes no. Aquí está mi código . ¿Qué me estoy perdiendo?
Tim
1
¿Alguien más ha tenido problemas con esto en iOS 9. Ya no funciona para mí en Safari.
bgolson
20

En iOS9, Apple finalmente introdujo la posibilidad de registrar su aplicación para manejar ciertas http://URL: enlaces universales .

Una explicación muy aproximada de cómo funciona:

  • Usted declara interés en abrir http://URL para ciertos dominios (URL web) en su aplicación.
  • En el servidor de los dominios especificados, debe indicar qué URL abrir en qué aplicación ha declarado interés en abrir URL del dominio del servidor.
  • El servicio de carga de URL de iOS verifica todos los intentos de abrir http://URL para una configuración como se explicó anteriormente y abre la aplicación correcta automáticamente si está instalada; sin pasar por Safari primero ...

Esta es la forma más limpia de hacer enlaces profundos en iOS, desafortunadamente solo funciona en iOS9 y versiones posteriores ...

severin
fuente
y no funciona dentro del navegador ... solo afuera, como por mensaje o notas
Mihey Mik
9

CONSTRUYENDO nuevamente sobre la respuesta de Nathan y JB:

Cómo iniciar la aplicación desde la url sin clic adicional Si prefiere una solución que no incluya el paso intermedio de hacer clic en un enlace, se puede utilizar lo siguiente. Con este javascript, pude devolver un objeto Httpresponse de Django / Python que inicia con éxito una aplicación si está instalada o, alternativamente, lanza la tienda de aplicaciones en caso de un tiempo de espera. Tenga en cuenta que también necesitaba ajustar el tiempo de espera de 500 a 100 para que esto funcione en un iPhone 4S. Pruebe y modifique para hacer lo correcto para su situación.

<html>
<head>
   <meta name="viewport" content="width=device-width" />
</head>
<body>

<script type="text/javascript">

// To avoid the "protocol not supported" alert, fail must open another app.
var appstorefail = "itms://itunes.apple.com/us/app/facebook/id284882215?mt=8&uo=6";

var loadedAt = +new Date;
setTimeout(
  function(){
    if (+new Date - loadedAt < 2000){
      window.location = appstorefail;
    }
  }
,100);

function LaunchApp(){
  window.open("unknown://nowhere","_self");
};
LaunchApp()
</script>
</body>
</html>
BFar
fuente
9
window.location = appurl;// fb://method/call..
!window.document.webkitHidden && setTimeout(function () {
    setTimeout(function () {
    window.location = weburl; // http://itunes.apple.com/..
    }, 100);
}, 600);

document.webkitHidden es detectar si su aplicación ya está invocada y la pestaña de safari actual pasa a segundo plano, este código es de www.baidu.com

zyanlu
fuente
Probé esta solución y descubrí que, aunque proporciona eventos correctamente, aparece momentáneamente el cuadro de diálogo de error "Safari no puede abrir esta página porque la dirección no es válida". (Se descarta automáticamente después de una fracción de segundo).
michaelhanson el
use un iframe para cargar appurly weburlpodría resolver su problema
zyanlu
1
@zyanlu: lo he intentado con iFrame. bt todavía safari muestra el mismo error.
kunjus
5

Si agrega un iframeen su página web con el srcesquema personalizado para su aplicación, iOS redirigirá automáticamente a esa ubicación en la aplicación. Si la aplicación no está instalada, no pasará nada. Esto le permite hacer un enlace profundo a la aplicación si está instalada, o redirigir a la App Store si no está instalada.

Por ejemplo, si tiene instalada la aplicación de Twitter y navega a una página web que contiene el siguiente marcado, se lo dirigirá inmediatamente a la aplicación.

<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    </head>
    <body>
        <iframe src="twitter://" width="0" height="0"></iframe>
        <p>Website content.</p>
    </body>
</html>

Aquí hay un ejemplo más completo que redirige a la tienda de aplicaciones si la aplicación no está instalada:

<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    <script src='//code.jquery.com/jquery-1.11.2.min.js'></script>
    <script src='//mobileesp.googlecode.com/svn/JavaScript/mdetect.js'></script>
    <script>
      (function ($, MobileEsp) {
        // On document ready, redirect to the App on the App store.
        $(function () {
          if (typeof MobileEsp.DetectIos !== 'undefined' && MobileEsp.DetectIos()) {
            // Add an iframe to twitter://, and then an iframe for the app store
            // link. If the first fails to redirect to the Twitter app, the
            // second will redirect to the app on the App Store. We use jQuery
            // to add this after the document is fully loaded, so if the user
            // comes back to the browser, they see the content they expect.
            $('body').append('<iframe class="twitter-detect" src="twitter://" />')
              .append('<iframe class="twitter-detect" src="itms-apps://itunes.com/apps/twitter" />');
          }
        });
      })(jQuery, MobileEsp);
    </script>
    <style type="text/css">
      .twitter-detect {
        display: none;
      }
    </style>
    </head>
    <body>
    <p>Website content.</p>
    </body>
</html>
q0rban
fuente
El problema con su primer ejemplo es que si vuelve a Mobile Safari, mostrará "La aplicación de Twitter no está instalada" a pesar de que Twitter se lanzó. Lo mismo con el segundo ejemplo, que muestra "Contenido del sitio web". Es necesario que haya un código que haga algo diferente (carga otra URL o muestra uno de los dos mensajes) si la aplicación está instalada.
mahboudz
1
Sí, @mahboudz, si lees el texto, es solo un ejemplo simple para mostrar que es posible redirigir automáticamente a la aplicación.
q0rban
Luego sigo con un ejemplo más completo que mostraría el contenido real del sitio web. Puedo eliminar el texto "La aplicación de Twitter no está instalada" si lo aclara.
q0rban
ios 6 todavía muestra una ventana emergente Esa página no se puede abrir debido a la URL no válida
Andrei Shender
@AndreiShender, aquí hay estadísticas de uso de iOS en el momento de escribir esto: monosnap.com/image/8eXUcpEUi8fm94DiMZIdiIp4xUNaln.png iOS 8: 72%, iOS 7: 25%, versiones anteriores: 3%
q0rban
4

Heres una solución.

Configure una situación booleana usando desenfoque y enfoque

//see if our window is active
window.isActive = true;
$(window).focus(function() { this.isActive = true; });
$(window).blur(function() { this.isActive = false; });

Vincula tu enlace con un controlador de clic jquery que llama a algo como esto.

function startMyApp(){
  document.location = 'fb://';

  setTimeout( function(){
    if (window.isActive) {
        document.location = 'http://facebook.com';
    }
  }, 1000);
}

Si se abre la aplicación, perderemos el foco en la ventana y el temporizador termina. de lo contrario no obtenemos nada y cargamos la URL de Facebook habitual.

Dane Macaulay
fuente
Muchas gracias por la sugerencia. Me enfrento al problema de que el diálogo "iniciar aplicación externa" parece ser suficiente para que el desenfoque desactive la bandera. Esto sucede incluso si la aplicación no está instalada (por ejemplo, al hacer clic en un enlace destinado a iniciar una aplicación de iPhone en un escritorio). Ideas?
fluxon
2

No puedo, hasta donde yo sé, hacer que todo el sistema operativo entienda una http:URL de dominio +. Solo puede registrar nuevos esquemas (los uso x-darkslide:en mi aplicación). Si la aplicación está instalada, Mobile Safari la iniciará correctamente.

Sin embargo, tendría que manejar el caso en el que la aplicación no está instalada con un "¿Todavía aquí? Haga clic en este enlace para descargar la aplicación desde iTunes". en tu página web.

Fraser Speirs
fuente
2
Esto ya no es correcto: con iOS9 y versiones recientes de Android, puede registrar su aplicación para escuchar ciertas httpURL
Severin
0

Verifique el User-Agent y, en caso de que sea Mobile Safari, abra myprotocol: // URL para (intentar) abrir la aplicación para iPhone y haga que abra Mobile iTunes para descargar la aplicación en caso de que el intento falle

Esto me parece un enfoque razonable, pero no creo que sea capaz de abrir iTunes móvil como segundo recurso. Creo que tendrá que elegir uno u otro, ya sea redirigir a su aplicación o iTunes.

es decir, si redirige a myprotocol: // y la aplicación no está en el teléfono, no tendrá una segunda oportunidad para redirigir a iTunes.

¿Tal vez podría primero redirigir a una página de destino (optimizada para iPhone) y darle al usuario la opción de hacer clic en su aplicación o en iTunes para obtener la aplicación si no la tienen? Pero dependerá de que el usuario haga lo correcto allí. (Editar: ¿aunque podría configurar una cookie para que sea solo una primera vez?)

frankodwyer
fuente
1
Eso está mal. Si se muestra un error de que la página no se puede abrir (aplicación no instalada), JS aún se ejecuta. Es por eso que puede redirigir a otra solución alternativa entonces.
Erik
0

Al tratar de solucionar el problema de la ventana emergente, descubrí que Apple tenía una forma de evitar esta preocupación.

De hecho, cuando hace clic en este enlace , si instaló la aplicación, se redirige a ella; de lo contrario, será redirigido a la página web, sin ninguna ventana emergente.

Titignes
fuente
3
Profundicé bastante en cómo funcionaba ese enlace, y lo mejor que puedo encontrar es que no es una solución de JavaScript en absoluto. Apple parece haber registrado un controlador de URL especial para su aplicación que no requiere un protocolo personalizado y, en cambio, coincide con una cadena de URL. El enlace que envía se redirige inmediatamente con un 303 aquí . Si envía ese enlace en un correo electrónico a ti mismo se puede observar que al hacer clic en él traerá directamente hasta la aplicación AppStore si está instalado
Casey
Muy interesante. Tienes razón: si hago clic en él, aparece la aplicación AppStore si está instalada. Pero si elimina algunos parámetros hasta "vacaciones", aparece en Safari. Apple puede registrar un esquema de URL especial ...
Titignes
@Titignes, ¿podría explicarnos de esta manera para abrir la aplicación o la página web? ¿Cuál es el patrón para construir tal url?
Andrei Shender