Est-il possible d'enregistrer un schéma d'URL basé sur le domaine http + pour les applications iPhone, comme YouTube et Maps?

223

J'aimerais avoir iOS pour ouvrir les URL de mon domaine (par exemple http://martijnthe.nl ) avec mon application chaque fois que l'application est installée sur le téléphone, et avec Mobile Safari dans le cas contraire.

J'ai lu qu'il est possible de créer un suffixe de protocole unique pour cela et de l'enregistrer dans Info.plist, mais Mobile Safari donnera une erreur au cas où l'application ne serait pas installée.

Quelle serait une solution de contournement?

Une idée:

1) Utilisez les URL http: // qui s'ouvrent dans n'importe quel navigateur de bureau et rendent le service via le navigateur

2) Vérifiez l'agent utilisateur et dans le cas où il s'agit de Mobile Safari, ouvrez une URL myprotocol: // pour (tenter) d'ouvrir l'application iPhone et demandez-lui d'ouvrir Mobile iTunes pour le téléchargement de l'application en cas d'échec de la tentative

Vous ne savez pas si cela fonctionnera ... des suggestions? Merci!

Martijn Thé
la source
4
Dans le métro de New York, il y a le wifi par Boingo qui vous offre un accès gratuit au WiFi si vous téléchargez une application qu'ils recommandent. Une fois que vous l'avez téléchargé, vous revenez à Safari et le navigateur détecte s'il a été installé, puis vous accorde l'accès. Une idée de comment ça se passe?
TommyG
2
Universal Links prend désormais en charge ce cas d'utilisation sans aucun message d'erreur. Voici comment configurer votre domaine et votre application: blog.branch.io/…
Alex Austin

Réponses:

243

Je pense que la façon la moins intrusive de procéder est la suivante:

  1. Vérifiez si l'agent utilisateur est celui d'un iPhone / iPod Touch
  2. Rechercher un appInstalled cookie
  3. Si le cookie existe et est défini sur true, défini window.locationsuryour-uri:// (ou effectuez la redirection côté serveur)
  4. Si le cookie n'existe pas, ouvrez un "Saviez-vous que le nom de votre site a une application iPhone?" modal avec un bouton "Oui, je l'ai déjà", "Non, mais j'adorerais l'essayer" et le bouton "Laissez-moi tranquille".
    1. Le bouton "Oui" définit le cookie sur vrai et redirige vers your-uri://
    2. Le bouton "Non" redirige vers " http://itunes.com/apps/yourappname " qui ouvrira l'App Store sur l'appareil
    3. Le bouton "Laissez-moi tranquille" met le cookie sur faux et ferme le modal

L'autre option avec laquelle j'ai joué mais que j'ai trouvé un peu maladroit était de faire ce qui suit 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
la source
16
Excellente solution. Si votre solution de repli est vers une autre application, elle se chargera IMMÉDIATEMENT sans afficher l'erreur. Donc au lieu de retomber sur itunes.com ... utilisez itms: //phobos.apple.com / ... pour éviter l'erreur popup!
jb.
47
Problème : en cas de window.location="custom-uri://réussite, le délai de repli n'est pas supprimé. Lorsque l'utilisateur retourne au navigateur depuis votre application, le minuteur est toujours là et lance le lien de l'App Store. Il s'agit d'une mauvaise expérience utilisateur.
JoJo
5
Il semble que les cookies soient placés dans un bac à sable dans # ios6, vous ne pouvez donc pas accéder aux cookies définis par une application à partir d'une autre. (App WebUI et Safari Mobile par exemple)
Olivier Amblet
2
Quelqu'un trouve-t-il un moyen d'empêcher le délai d'expiration d'origine de se déclencher lorsque l'utilisateur revient sur le navigateur? (le problème surévalué que JoJo mentionne)
cobolstinks
2
Pour résoudre le problème mentionné par JoJo, n'exécutez le code dans le délai d'expiration que si "beaucoup de temps" s'est écoulé depuis que l'utilisateur a cliqué sur le lien. Voir cette solution: stackoverflow.com/a/14751543/533420
kkara
95

Il est tout à fait possible de le faire en JavaScript tant que votre solution de rechange est un autre lien. S'appuyant sur la suggestion 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>

Découvrez une démo en direct ici .

jb.
la source
7
D'accord avec Lee, cela semble être une solution plus simple - même si je reçois toujours le message d'erreur de safari si l'application n'existe pas et qu'elle redirige vers l'App Store.
Jon
2
J'ai utilisé cette solution pour Android et iOS. J'ai constaté que si je modifiais la valeur du délai d'expiration de 500 à 100, je n'obtenais pas la boîte de dialogue contextuelle "Impossible d'ouvrir la page" dans iOS. J'ai également constaté que le délai d'attente doit être de 50 pour Android
Rossini
14
L'utilisation de "itms-apps:" au lieu de "itms:" enregistre 1 redirection et ouvre directement la page de l'application dans l'appstore.
German Latorre
6
@Rossini, cela est intégré à Android en configurant un filtre d'intention pour votre action qui répond à un hôte particulier
jwadsack
9
Quelqu'un sait-il comment éviter le message d'erreur "impossible d'ouvrir la page" de safari si l'application n'est pas installée et avant de rediriger vers l'App Store?
davidk
24

J'ai trouvé que la réponse sélectionnée fonctionne pour les applications de navigateur, mais je rencontrais des problèmes avec le code fonctionnant dans les applications sans navigateur qui implémentent un UIWebView .

Le problème pour moi était qu'un utilisateur de l'application Twitter cliquait sur un lien qui les mènerait à mon site via un UIWebViewdans l'application Twitter. Puis, quand ils ont cliqué sur un bouton de mon site, Twitter essaie d'être fantaisiste et ne le complète que window.locationsi le site est accessible. Donc, ce qui se passe est un UIAlertViewpop-up disant que vous êtes sûr de vouloir continuer, puis redirige immédiatement vers l'App Store sans deuxième pop-up.

Ma solution implique des iframes. Cela évite d' UIAlertViewêtre présenté permettant une expérience utilisateur simple et élégante.

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://');

ÉDITER:

Ajoutez une position absolue à l'iframe afin qu'il n'y ait pas un espace aléatoire au bas de la page lorsqu'il est inséré.

Il est également important de noter que je n'ai pas trouvé de besoin pour cette approche avec Android. L'utilisation window.location.hrefdevrait fonctionner correctement.

cnotethegr8
la source
1
Ça marche!! Merci, j'ai enfin trouvé une solution qui fonctionne sur tous les navigateurs.
koleror
2
C'est la meilleure solution si elle est trouvée. Je vous remercie. Il n'y a plus de popup d'erreur.
confile le
1
@Tim si vous voulez que ce code soit déclenché lorsqu'un lien est cliqué, enveloppez ce code dans une fonction qui est appelée une fois que le lien est cliqué.
cnotethegr8
1
@ cnotethegr8 Je l'ai mis dans une fonction et rediriger vers une URL personnalisée fonctionne très bien mais pas vers iTunes. Voici mon code . Qu'est-ce que je rate?
Tim
1
Quelqu'un d'autre a-t-il eu des problèmes avec cela dans iOS 9. Cela ne fonctionne plus pour moi dans Safari.
bgolson
20

Dans iOS9, Apple a enfin introduit la possibilité d'enregistrer votre application pour gérer certaines http://URL: Universal Links .

Une explication très approximative de son fonctionnement:

  • Vous déclarez http://vouloir ouvrir des URL pour certains domaines (URL Web) dans votre application.
  • Sur le serveur des domaines spécifiés, vous devez indiquer les URL à ouvrir dans quelle application qui a déclaré vouloir ouvrir des URL à partir du domaine du serveur.
  • Le service de chargement d'URL iOS vérifie toutes les tentatives d'ouverture d' http://URL pour une configuration comme expliqué ci-dessus et ouvre automatiquement l'application correcte si elle est installée; sans passer par Safari d'abord ...

C'est le moyen le plus propre de créer des liens profonds sur iOS, malheureusement cela ne fonctionne que dans iOS9 et plus récent ...

Severin
la source
et cela ne fonctionne pas à l'intérieur du navigateur ... seulement à l'extérieur, comme dans l'imessage ou les notes
Mihey Mik
9

CONSTRUIRE à nouveau sur la réponse de Nathan et JB:

Comment lancer l'application à partir de l'URL sans clic supplémentaire Si vous préférez une solution qui n'inclut pas l'étape intermédiaire de cliquer sur un lien, les options suivantes peuvent être utilisées. Avec ce javascript, j'ai pu renvoyer un objet Httpresponse de Django / Python qui lance avec succès une application si elle est installée ou bien lance la boutique d'applications en cas de time out. Remarque J'ai également dû ajuster le délai d'expiration de 500 à 100 pour que cela fonctionne sur un iPhone 4S. Testez et ajustez pour l'adapter à votre situation.

<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
la source
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 est de détecter si votre application est déjà invoquée et que l'onglet safari actuel passe en arrière-plan, ce code provient de www.baidu.com

zyanlu
la source
J'ai testé cette solution et j'ai constaté que, bien qu'elle fournisse correctement les événements, la boîte de dialogue d'erreur "Safari ne peut pas ouvrir cette page car l'adresse n'est pas valide" apparaît momentanément. (Il disparaît automatiquement après une fraction de seconde).
michaelhanson
utiliser un iframe pour charger appurlet weburlpourrait résoudre votre problème
zyanlu
1
@zyanlu: j'ai essayé avec iFrame. bt encore safari affiche la même erreur.
kunjus
5

Si vous ajoutez un iframesur votre page Web avec lesrc schéma défini sur personnalisé pour votre application, iOS redirigera automatiquement vers cet emplacement dans l'application. Si l'application n'est pas installée, rien ne se passera. Cela vous permet de créer un lien profond vers l'application si elle est installée, ou de rediriger vers l'App Store si elle n'est pas installée.

Par exemple, si vous avez installé l'application Twitter et accédez à une page Web contenant le balisage suivant, vous serez immédiatement dirigé vers l'application.

<!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>

Voici un exemple plus complet qui redirige vers l'App Store si l'application n'est pas installée:

<!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
la source
Le problème avec votre premier exemple est que si vous revenez à Mobile Safari, il affichera "L'application Twitter n'est pas installée" même si Twitter a été lancé. Idem avec le deuxième exemple, affichant le "contenu du site Web". Il doit y avoir du code qui fait quelque chose de différent (charge une autre URL ou affiche l'un des deux messages) si l'application est installée.
mahboudz
1
Oui, @mahboudz, si vous lisez le texte, ce n'est qu'un exemple simple pour montrer qu'il est possible de rediriger automatiquement vers l'application.
q0rban
Je fais ensuite un suivi avec un exemple plus complet qui montrerait le contenu réel du site Web. Je peux supprimer le texte "L'application Twitter n'est pas installée" si cela le rend plus clair.
q0rban
ios 6 affiche toujours une popup Cette page ne peut pas être ouverte en raison de l'url invalide
Andrei Shender
@AndreiShender, voici les statistiques d'utilisation iOS au moment d'écrire ces lignes : monosnap.com/image/8eXUcpEUi8fm94DiMZIdiIp4xUNaln.png iOS 8: 72%, iOS 7: 25%, Versions antérieures: 3%
q0rban
4

Voici une solution.

Configurer une sitiation booléenne en utilisant le flou et la mise au point

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

Liez votre lien avec un gestionnaire de clics jquery qui appelle quelque chose comme ça.

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

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

si l'application s'ouvre, nous perdrons le focus sur la fenêtre et le chronomètre se termine. sinon nous n'obtenons rien et nous chargeons l'url facebook habituelle.

Dane Macaulay
la source
Merci beaucoup pour la suggestion. Je suis confronté au problème que le dialogue "lancer une application externe" semble être suffisant pour que le flou inactive le drapeau. Cela se produit même si l'application n'est pas installée (par exemple, lorsque vous cliquez sur un lien destiné à lancer une application iPhone sur un bureau). Des idées?
fluxon
2

Pour autant que je sache, vous ne pouvez pas faire comprendre à l'ensemble du système d'exploitation une http:URL de domaine +. Vous ne pouvez enregistrer que de nouveaux régimes (j'utilise x-darkslide:dans mon application). Si l'application est installée, Mobile Safari lancera l'application correctement.

Cependant, vous devrez gérer le cas où l'application n'est pas installée avec un "Toujours ici? Cliquez sur ce lien pour télécharger l'application depuis iTunes." dans votre page Web.

Fraser Speirs
la source
2
Ce ne plus est correcte: avec iOS9 et récentes versions Android , vous pouvez enregistrer votre application pour écouter certaines httpURL
severin
0

Vérifiez l'agent utilisateur et dans le cas où il s'agit de Mobile Safari, ouvrez une URL myprotocol: // pour (tenter) d'ouvrir l'application iPhone et demandez-lui d'ouvrir Mobile iTunes pour le téléchargement de l'application en cas d'échec de la tentative

Cela me semble une approche raisonnable, mais je ne pense pas que vous pourrez l'obtenir pour ouvrir des itunes mobiles en deuxième recours. Je pense que vous devrez choisir l'un ou l'autre - soit rediriger vers votre application ou vers iTunes.

Par exemple, si vous redirigez vers myprotocol: //, et que l'application n'est pas sur le téléphone, vous n'aurez pas une seconde chance de rediriger vers iTunes.

Vous pourriez peut-être d'abord rediriger vers une page de destination (optimisée pour l'iphone) et donner à l'utilisateur la possibilité de cliquer sur votre application, ou sur iTunes pour obtenir l'application s'il ne l'a pas? Mais, vous comptez sur l'utilisateur pour faire la bonne chose là-bas. (Modifier: bien que vous puissiez définir un cookie afin que ce soit une première chose uniquement?)

Frankodwyer
la source
1
C'est faux. Si une erreur indique que la page ne peut pas être ouverte (application non installée), JS est toujours exécuté. C'est pourquoi vous pouvez alors rediriger vers une autre solution de secours.
Erik
0

En cherchant à résoudre le problème des fenêtres pop-up, j'ai découvert qu'Apple avait une solution à ce problème.

En effet, lorsque vous cliquez sur ce lien , si vous avez installé l'application, elle est redirigée vers celle-ci; sinon, vous serez redirigé vers la page Web, sans aucune fenêtre contextuelle.

Titignes
la source
3
J'ai approfondi la façon dont ce lien fonctionnait, et le mieux que je puisse trouver, c'est que ce n'est pas du tout une solution JavaScript. Apple semble avoir enregistré un gestionnaire d'URL spécial pour son application qui ne nécessite pas de protocole personnalisé et correspond à la place à une chaîne d'URL. Le lien que vous envoyez redirige immédiatement avec un 303 vers ici . Si vous vous envoyez ce lien dans un e-mail, vous pouvez constater qu'en cliquant dessus, l'application AppStore s'affichera directement si elle est installée
Casey
Très intéressant. Vous avez raison: si je clique dessus, l'application AppStore s'affiche si elle est installée. Mais si vous supprimez certains paramètres jusqu'à "vacances", cela apparaît dans Safari. Apple peut enregistrer un schéma d'URL spécial ...
Titignes
@Titignes, pourriez-vous nous expliquer comment ouvrir l'application ou la page Web? Quel est le modèle de construction d'une telle URL?
Andrei Shender