Comment vérifier si une application est installée à partir d'une page Web sur un iPhone?

142

Je souhaite créer une page Web, une page qui redirigera un iPhone vers l'App-Store si l'application n'est pas installée sur l'iPhone, mais si l'application est installée sur l'iPhone, je veux qu'elle ouvre l'application.

J'ai déjà implémenté une URL personnalisée dans l'application iPhone, j'ai donc une URL pour l'application qui ressemble à quelque chose comme:

myapp://

Et si cette URL n'est pas valide, je souhaite que la page soit redirigée vers l'App Store. Est-ce possible?

Si l'application n'est pas installée sur le téléphone et que j'écris l'url myapp: // dans safari, tout ce que j'obtiens est un message d'erreur.

Même s'il existe un vilain hack avec javascript j'aimerais vraiment savoir?

Joakim Engstrom
la source
1
Cela ne cesse de changer dans chaque version iOS - iOS9 vient de tout casser à nouveau. Je vous recommande d'utiliser un service comme branch.io pour s'occuper de cela pour vous. J'ai aidé à construire des parties du service de liaison de branche, et il gère actuellement plus de 6000 cas de bord de redirection différents ... fou.
Alex Austin
1
En 2017, si votre besoin est de créer un lien vers votre application à partir d'e-mails, vous devriez plutôt jeter un œil à ma réponse: stackoverflow.com/questions/13044805/…
Sebastien Lorber

Réponses:

198

Autant que je sache, vous ne pouvez pas, à partir d'un navigateur, vérifier si une application est installée ou non.

Mais vous pouvez essayer de rediriger le téléphone vers l'application, et si rien ne se passe, redirigez le téléphone vers une page spécifiée, comme ceci:

setTimeout(function () { window.location = "https://itunes.apple.com/appdir"; }, 25);
window.location = "appname://";

Si la deuxième ligne de code donne un résultat, la première ligne n'est jamais exécutée.

J'espère que cela t'aides!

Question similaire:

missemisa
la source
20
Actuellement dans iOS 6.1.2, cela semble fonctionner uniquement en mode webapp. Si vous utilisez l'application directement à partir du navigateur, elle ouvre l'application externe comme prévu, mais le délai d'expiration est également déclenché et le navigateur est redirigé.
Mika Tuupola
4
Si l'application n'est pas installée, elle lance une vilaine alerte «page non trouvée». Quoi qu'il en soit, nous pouvons supprimer cela
Akshat Agarwal
3
@AkshatAgarwal, pouvez-vous s'il vous plaît expliquer comment coder pour supprimer `` l'alerte de page introuvable ''
Harpreet
2
Il existe maintenant de nouvelles façons de l'implémenter dans Android et iOS. Jetez un œil aux liens d'applications Android et aux liens universels iOS
maledr53
1
Il ouvre l'application mais redirige également le navigateur vers l'Appstore / Playstore. Une méthode / un hack pour éviter cela?
Sujeet Kumar
157

Pour approfondir la réponse acceptée, vous devez parfois ajouter du code supplémentaire pour gérer les personnes qui retournent le navigateur après le lancement de l'application - cette fonction setTimeout s'exécutera chaque fois qu'elles le feront. Alors, je fais quelque chose comme ça:

var now = new Date().valueOf();
setTimeout(function () {
    if (new Date().valueOf() - now > 100) return;
    window.location = "https://itunes.apple.com/appdir";
}, 25);
window.location = "appname://";

De cette façon, s'il y a eu un gel dans l'exécution du code (c.-à-d. Changement d'application), il ne fonctionnera pas.

Alastair
la source
2
Cette solution est bien meilleure que d'autres, j'ai du incrémenter le temps sur 50
Magico
1
Mon commentaire sur son échec sur iOS 7 était faux: je devais simplement augmenter les 100 ms à quelques secondes (pas besoin que ce soit si court de toute façon vraiment).
devios1
Au lieu de itunes.apple.com/appdir , enregistrez une étape (sans attendre une redirection http) et créez un lien directement vers le schéma d'URL de l' App Store. Par exemple: itms: //itunes.apple.com/us/app/yelp/id284910350
Justin
Génial, cela fonctionne bien pour les applications iOS, le même code est redirigé vers les deux URL en même temps dans les applications Android. avez-vous fait pour Android pour ouvrir des applications et Play Store?
Mehul Dudhat
6
Cela ouvre systématiquement mon application et l'App Store, même à 50 ans. IOS 12
Josh Wolff
27

iOS Safari a une fonctionnalité qui vous permet d'ajouter une bannière «intelligente» à votre page Web qui sera liée soit à votre application, si elle est installée, soit à l'App Store.

Pour ce faire, ajoutez une metabalise à la page. Vous pouvez même spécifier une URL d'application détaillée si vous souhaitez que l'application fasse quelque chose de spécial lors de son chargement.

Les détails se trouvent sur la page de promotion des applications d' Apple avec des bannières d'applications intelligentes .

Le mécanisme présente les avantages d'être simple et de présenter une bannière standardisée. L'inconvénient est que vous n'avez pas beaucoup de contrôle sur l'apparence ou l'emplacement. De plus, tous les paris sont désactivés si la page est affichée dans un navigateur autre que Safari.

cerveau
la source
2
Mais il n'affiche pas la bannière de l'application si l'utilisateur ne l'a pas installé
TomSawyer
Ni les liens universels ni les bannières intelligentes ne fonctionnent pour moi. J'ai besoin de plusieurs liens d'applications natives vers différentes applications. Chacun avec un Check IF Installed, lancez-le, sinon allez dans le magasin. Je n'ai pas non plus le contrôle des domaines vers lesquels télécharger le fichier de propriété pour les liens universels. Les deux options sont donc écartées pour moi. Besoin d'une solution javascript pure.
FranticRock
16

À partir de 2017, il semble qu'il n'y ait aucun moyen fiable de détecter qu'une application est installée, et l'astuce de redirection ne fonctionnera pas partout.

Pour ceux comme moi qui ont besoin de créer un lien profond directement à partir d'e-mails (assez courant), il convient de noter ce qui suit:

  • L'envoi d'e-mails avec appScheme: // ne fonctionnera pas correctement car les liens seront filtrés dans Gmail

  • La redirection automatique vers appScheme: // est bloquée par Chrome: je suppose que Chrome nécessite que la redirection soit synchrone à une interaction de l'utilisateur (comme un clic)

  • Vous pouvez maintenant créer un lien profond sans appScheme: // et c'est mieux, mais cela nécessite une plate-forme moderne et une configuration supplémentaire. Android iOS


Il convient de noter que d'autres personnes y ont déjà réfléchi en profondeur. Si vous regardez comment Slack implémente sa fonction de "lien magique", vous pouvez remarquer que:

  • Il envoie un e-mail avec un lien http normal (ok avec Gmail)
  • La page Web a un gros bouton qui renvoie à appScheme: // (ok avec Chrome)
Sébastien Lorber
la source
9

Vous pouvez consulter ce plugin qui tente de résoudre le problème. Il est basé sur la même approche que celle décrite par missemisa et Alastair etc., mais utilise à la place une iframe cachée.

https://github.com/hampusohlsson/browser-deeplink

hampusohlsson
la source
J'ai ajouté ceci, mais il redirige vers l'Appstore même après avoir installé l'application.
Qasim
9

@Alistair a souligné dans cette réponse que parfois les utilisateurs reviennent au navigateur après l'ouverture de l'application. Un commentateur à cette réponse a indiqué que les valeurs de temps utilisées devaient être modifiées en fonction de la version d'iOS. Lorsque notre équipe a dû faire face à cela, nous avons constaté que les valeurs de temps pour le délai d'expiration initial et indiquer si nous étions retournés au navigateur devaient être réglées, et souvent ne fonctionnaient pas pour tous les utilisateurs et appareils.

Plutôt que d'utiliser un seuil de différence de temps arbitraire pour déterminer si nous étions retournés au navigateur, il était logique de détecter les événements "pagehide" et "pageshow".

J'ai développé la page Web suivante pour aider à diagnostiquer ce qui se passait. Il ajoute des diagnostics HTML au fur et à mesure que les événements se déroulent, principalement parce que l'utilisation de techniques telles que la journalisation de la console, les alertes ou l'inspecteur Web, jsfiddle.net, etc. avaient tous leurs inconvénients dans ce flux de travail. Plutôt que d'utiliser un seuil de temps, le Javascript compte le nombre d'événements "pagehide" et "pageshow" pour voir s'ils se sont produits. Et j'ai trouvé que la stratégie la plus robuste était d'utiliser un délai initial de 1000 (plutôt que les 25, 50 ou 100 rapportés / suggérés par d'autres).

Cela peut être servi sur un serveur local, par exemple python -m SimpleHTTPServeret affiché sur iOS Safari.

Pour jouer avec, appuyez sur les liens «Ouvrir une application installée» ou «Application non installée». Ces liens doivent provoquer respectivement l'ouverture de l'application Maps ou de l'App Store. Vous pouvez ensuite retourner dans Safari pour voir la séquence et le calendrier des événements.

(Remarque: cela ne fonctionnera que pour Safari. Pour les autres navigateurs (comme Chrome), vous devrez installer des gestionnaires pour les événements pagehide / show-equivalent).

Mise à jour: comme @Mikko l'a souligné dans les commentaires, les événements pageshow / pagehide que nous utilisons ne sont apparemment plus pris en charge dans iOS8.

<html>
<head>
</head>
<body>
<a href="maps://" onclick="clickHandler()">Open an installed app</a>
<br/><br/>
<a href="xmapsx://" onclick="clickHandler()">App not installed</a>
<br/>

<script>

var hideShowCount = 0 ;
window.addEventListener("pagehide", function() {
    hideShowCount++ ;
    showEventTime('pagehide') ;
});

window.addEventListener("pageshow", function() {
    hideShowCount++ ;
    showEventTime('pageshow') ;
});

function clickHandler(){
    var hideShowCountAtClick = hideShowCount ;
    showEventTime('click') ;
    setTimeout(function () {
               showEventTime('timeout function '+(hideShowCount-hideShowCountAtClick)+' hide/show events') ;
               if (hideShowCount == hideShowCountAtClick){
                    // app is not installed, go to App Store
                    window.location = 'http://itunes.apple.com/app' ;
               }
            }, 1000);
}

function currentTime()
{
    return Date.now()/1000 ;
}

function showEventTime(event){
    var time = currentTime() ;
    document.body.appendChild(document.createElement('br'));
    document.body.appendChild(document.createTextNode(time+' '+event));
}
</script>
</body>
</html>
cerveau
la source
2

J'ai besoin de faire quelque chose comme ça, j'ai fini par choisir la solution suivante.

J'ai une URL de site Web spécifique qui ouvrira une page avec deux boutons

1) Button One aller sur le site Web

2) Bouton deux aller à l'application (iphone / téléphone Android / tablette), vous pouvez revenir à un emplacement par défaut à partir d'ici si l'application n'est pas installée (comme une autre URL ou un magasin d'applications)

3) cookie pour mémoriser le choix des utilisateurs

<head>
<title>Mobile Router Example </title>


<script type="text/javascript">
    function set_cookie(name,value)
    {
       // js code to write cookie
    }
    function read_cookie(name) {
       // jsCode to read cookie
    }

    function goToApp(appLocation) {
        setTimeout(function() {
            window.location = appLocation;
              //this is a fallback if the app is not installed. Could direct to an app store or a website telling user how to get app


        }, 25);
        window.location = "custom-uri://AppShouldListenForThis";
    }

    function goToWeb(webLocation) {
        window.location = webLocation;
    }

    if (readCookie('appLinkIgnoreWeb') == 'true' ) {
        goToWeb('http://somewebsite');

    }
    else if (readCookie('appLinkIgnoreApp') == 'true') {
        goToApp('http://fallbackLocation');
    }



</script>
</head>
<body>


<div class="iphone_table_padding">
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <!-- INTRO -->
            <span class="iphone_copy_intro">Check out our new app or go to website</span>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_btn_padding">

                <!-- GET IPHONE APP BTN -->
                <table border="0" cellspacing="0" cellpadding="0" class="iphone_btn" onclick="set_cookie('appLinkIgnoreApp',document.getElementById('chkDontShow').checked);goToApp('http://getappfallback')">
                    <tr>
                        <td class="iphone_btn_on_left">&nbsp;</td>
                        <td class="iphone_btn_on_mid">
                            <span class="iphone_copy_btn">
                                Get The Mobile Applications
                            </span>
                        </td>
                        <td class="iphone_btn_on_right">&nbsp;</td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_btn_padding">

                <table border="0" cellspacing="0" cellpadding="0" class="iphone_btn"  onclick="set_cookie('appLinkIgnoreWeb',document.getElementById('chkDontShow').checked);goToWeb('http://www.website.com')">
                    <tr>
                        <td class="iphone_btn_left">&nbsp;</td>
                        <td class="iphone_btn_mid">
                            <span class="iphone_copy_btn">
                                Visit Website.com
                            </span>
                        </td>
                        <td class="iphone_btn_right">&nbsp;</td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_chk_padding">

                <!-- CHECK BOX -->
                <table border="0" cellspacing="0" cellpadding="0">
                    <tr>
                        <td><input type="checkbox" id="chkDontShow" /></td>
                        <td>
                            <span class="iphone_copy_chk">
                                <label for="chkDontShow">&nbsp;Don&rsquo;t show this screen again.</label>
                            </span>
                        </td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
</table>

</div>

</body>
</html>
nate_weldon
la source
J'ai besoin de ce type de code pour mes besoins mais je n'arrive pas à placer mes liens. Condition: si app1 est installé, allez sur Link 1, sinon allez sur Link2. Puis-je avoir une aide s'il vous plait?
SFDC_Learner
Il est nécessaire de désactiver le cookie lorsque l'application est installée, au cas où l'utilisateur choisit le premier site Web.
Charlie Reitzel
1

Après avoir compilé quelques réponses, j'ai trouvé le code suivant. Ce qui m'a surpris est que la minuterie ne pas se congeler sur un PC (Chrome, FF) ou Android Chrome - la gâchette a travaillé en arrière - plan, et la vérification de la visibilité était la seule information fiable.

var timestamp             = new Date().getTime();
var timerDelay              = 5000;
var processingBuffer  = 2000;

var redirect = function(url) {
  //window.location = url;
  log('ts: ' + timestamp + '; redirecting to: ' + url);
}
var isPageHidden = function() {
    var browserSpecificProps = {hidden:1, mozHidden:1, msHidden:1, webkitHidden:1};
    for (var p in browserSpecificProps) {
        if(typeof document[p] !== "undefined"){
        return document[p];
      }
    }
    return false; // actually inconclusive, assuming not
}
var elapsedMoreTimeThanTimerSet = function(){
    var elapsed = new Date().getTime() - timestamp;
  log('elapsed: ' + elapsed);
  return timerDelay + processingBuffer < elapsed;
}
var redirectToFallbackIfBrowserStillActive = function() {
  var elapsedMore = elapsedMoreTimeThanTimerSet();
  log('hidden:' + isPageHidden() +'; time: '+ elapsedMore);
  if (isPageHidden() || elapsedMore) {
    log('not redirecting');
  }else{
    redirect('appStoreUrl');
  }
}
var log = function(msg){
    document.getElementById('log').innerHTML += msg + "<br>";
}

setTimeout(redirectToFallbackIfBrowserStillActive, timerDelay);
redirect('nativeApp://');

JS Fiddle

ptrk
la source
-2

La solution de date est bien meilleure que les autres, j'ai dû incrémenter l'heure sur 50 comme ça c'est un exemple de Tweeter:

//on click or your event handler..
var twMessage = "Your Message to share";
var now = new Date().valueOf();
setTimeout(function () {
   if (new Date().valueOf() - now > 100) return;
   var twitterUrl = "https://twitter.com/share?text="+twMessage;
   window.open(twitterUrl, '_blank');
}, 50);
window.location = "twitter://post?message="+twMessage;

le seul problème sur Mobile IOS Safari est lorsque l'application n'est pas installée sur l'appareil, et Safari affiche donc une alerte qui échoue automatiquement lorsque la nouvelle URL est ouverte, de toute façon est une bonne solution pour le moment!

Magico
la source
1
@AkshatAgarwal car c'est la même solution que celle d'alastair publiée 7 jours plus tard
albanx
-5

Je n'ai pas lu tout cela, mais peut-être utiliser un iframe et ajouter la source à "mon application: // peu importe".

Ensuite, vérifiez régulièrement l'intervalle défini de la page est 404ou non.

Vous pouvez également utiliser l'appel Ajax. Si la réponse 404, l'application n'est pas installée.

1,21 gigawatts
la source
Cette solution sans souci.
Andrey M.