É possível registrar um esquema de URL baseado em domínio http + para aplicativos do iPhone, como YouTube e Maps?

223

Gostaria de ter o iOS para abrir URLs do meu domínio (por exemplo, http://martijnthe.nl ) com meu aplicativo sempre que o aplicativo estiver instalado no telefone e com o Mobile Safari, caso não esteja.

Eu li que é possível criar um sufixo de protocolo exclusivo para isso e registrá-lo no Info.plist, mas o Mobile Safari apresentará um erro caso o aplicativo não esteja instalado.

O que seria uma solução alternativa?

Uma ideia:

1) Use http: // URLs que abrem em qualquer navegador da área de trabalho e prestam o serviço através do navegador

2) Verifique o User-Agent e, no caso do Mobile Safari, abra um myprotocol: // URL para (tentativa) para abrir o aplicativo para iPhone e abra o Mobile iTunes para baixar o aplicativo, caso a tentativa falhe

Não tem certeza se isso vai funcionar ... sugestões? Obrigado!

Martijn Thé
fonte
4
No metrô de Nova York, há Wi-Fi da Boingo, que fornece acesso gratuito a Wi-Fi se você baixar um aplicativo que eles recomendam. Depois de baixá-lo, você volta ao Safari e o navegador detecta se ele foi instalado e concede acesso. Alguma idéia de como isso está sendo feito?
TommyG
2
O Universal Links agora suporta esse caso de uso sem nenhuma mensagem de erro. Veja como configurar o seu domínio e app: blog.branch.io/...
Alex Austin

Respostas:

243

Eu acho que a maneira menos invasiva de fazer isso é a seguinte:

  1. Verifique se o agente do usuário é o de um iPhone / iPod Touch
  2. Verifique se há um appInstalledcookie
  3. Se o cookie existir e estiver definido como true, defina window.locationcomo your-uri://(ou faça o redirecionamento do lado do servidor)
  4. Se o cookie não existir, abra a mensagem "Você sabia que o nome do seu site tem um aplicativo para iPhone?" modal com um "Sim, eu já entendi", "Não, mas eu adoraria tentar" e "Deixe-me em paz".
    1. O botão "Sim" define o cookie como true e redireciona para your-uri://
    2. O botão "Não" é redirecionado para " http://itunes.com/apps/yourappname ", que abrirá a App Store no dispositivo
    3. O botão "Deixe-me em paz" define o cookie como falso e fecha o modal

A outra opção com a qual eu joguei, mas achei um pouco desajeitada, foi fazer o seguinte em 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
fonte
16
Ótima solução. Se o seu fallback for para outro aplicativo, ele será carregado IMEDIATAMENTE sem exibir o erro. Então, em vez de voltar ao itunes.com ... use itms: //phobos.apple.com / ... para evitar o erro pop-up!
jb.
47
Problema : Quando window.location="custom-uri://for bem-sucedido, o tempo limite de fallback não será eliminado. Quando o usuário retorna ao navegador a partir do seu aplicativo, o timer ainda está lá e inicia o link da loja de aplicativos. Esta é uma má experiência do usuário.
JoJo
5
Parece que os cookies estão em área restrita no # ios6, portanto você não pode acessar o cookie definido por um aplicativo de outro. (App WebUI e Safari Mobile, por exemplo)
Olivier Amblet 25/01
2
Alguém encontrou uma maneira de impedir que o tempo limite original seja acionado quando o usuário voltar ao navegador? (o problema votado que JoJo menciona)
cobolstinks
2
Para resolver o problema mencionado por JoJo, execute apenas o código no tempo limite se não tiver passado "muito tempo" desde que o usuário clicou no link. Veja esta solução: stackoverflow.com/a/14751543/533420
kkara
95

É bem possível fazer isso em JavaScript, desde que seu fallback seja outro applink. Com base na sugestão 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>

Confira uma demonstração ao vivo aqui .

jb.
fonte
7
Concordo com Lee, esta parece ser uma solução mais direta - embora eu ainda receba a mensagem de erro do safari se o aplicativo não existir e ele redirecionar para a loja de aplicativos.
31411 Jon
2
Eu usei esta solução para Android e iOS. Descobri que se eu alterar o valor do tempo limite de 500 para 100, não recebo a caixa de diálogo pop-up "Não é possível abrir a página" no iOS. Eu também achei que as necessidades de tempo de espera para ser 50 para Android
Rossini
14
O uso de "itms-apps:" em vez de "itms:" salva 1 redirecionamento e abre diretamente a página do aplicativo na appstore.
German Latorre
6
@Rossini este é construído em Android através da criação de um filtro de intenção para a ação que responde a um determinado host
jwadsack
9
Alguém sabe como evitar a mensagem de erro "não é possível abrir a página" do safari se o aplicativo não estiver instalado e antes de redirecionar para a loja de aplicativos?
davidk 7/09/12
24

Descobri que a resposta selecionada funciona para os aplicativos de navegador, mas eu estava tendo problemas com o código que trabalhava em aplicativos que não são de navegador que implementam a UIWebView.

O problema para mim era que um usuário do aplicativo do Twitter clicaria em um link que os levaria ao meu site por meio de um UIWebViewaplicativo do Twitter. Então, quando eles clicaram em um botão do meu site, o Twitter tenta ser chique e só completa window.locationse o site estiver acessível. Então, o que acontece é um UIAlertViewpop-up dizendo que você tem certeza de que deseja continuar e, em seguida, redireciona imediatamente para a App Store sem um segundo pop-up.

Minha solução envolve iframes. Isso evita a UIAlertViewapresentação, permitindo uma experiência de usuário simples e 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:

Adicione posição absoluta ao iframe para que, quando inserido, não haja um espaço aleatório de espaço em branco na parte inferior da página.

Também é importante observar que eu não encontrei a necessidade dessa abordagem com o Android. Usar window.location.hrefdeve funcionar bem.

cnotethegr8
fonte
1
Funciona!! Obrigado, finalmente encontrei uma solução que funciona em todos os navegadores.
precisa saber é o seguinte
2
Esta é a melhor solução se encontrada. Obrigado. Não há mais pop-up de erro.
confile
1
@ Tim, se você quiser que esse código seja acionado quando um link for clicado, do que agrupar esse código em uma função chamada quando o link for clicado.
cnotethegr8
1
@ cnotethegr8 Coloquei-o em uma função e redireciono para url personalizado funciona muito bem, mas o retorno ao iTunes não. Aqui está o meu código . o que estou perdendo?
Tim
1
Alguém já teve problemas com isso no iOS 9. Ele não funciona mais para mim no Safari.
bgolson
20

No iOS9, a Apple finalmente introduziu a possibilidade de registrar seu aplicativo para lidar com certos http://URLs: Links universais .

Uma explicação muito grosseira de como funciona:

  • Você declara interesse em abrir http://URLs para determinados domínios (URLs da Web) em seu aplicativo.
  • No servidor dos domínios especificados, você deve indicar quais URLs abrir em qual aplicativo que declarou interesse em abrir URLs do domínio do servidor.
  • O serviço de carregamento de URL do iOS verifica todas as tentativas de abrir http://URLs para uma configuração, conforme explicado acima e abre o aplicativo correto automaticamente, se instalado; sem passar pelo Safari primeiro ...

Esta é a maneira mais limpa de criar links diretos no iOS, infelizmente, funciona apenas no iOS9 e mais recente ...

severin
fonte
e ele não funciona dentro do navegador ... somente fora, como de imessage ou notas
Mihey Mik
9

CONSTRUINDO Novamente na resposta de Nathan e JB:

Como iniciar o aplicativo a partir do URL sem clique extra Se você preferir uma solução que não inclua a etapa intermediária de clicar em um link, pode ser usado o seguinte. Com esse javascript, consegui retornar um objeto Httpresponse do Django / Python que inicia com êxito um aplicativo se ele estiver instalado ou, alternativamente, inicia a loja de aplicativos no caso de um tempo limite. Observe que eu também precisava ajustar o período de tempo limite de 500 a 100 para que isso funcionasse em um iPhone 4S. Teste e ajuste para corrigir a situação.

<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
fonte
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 é detectar se seu aplicativo já foi chamado e a guia safari atual está em segundo plano, esse código é de www.baidu.com

zyanlu
fonte
Testei esta solução e descobri que, embora ela entregue eventos corretamente, a caixa de diálogo "O Safari não pode abrir esta página porque o endereço é inválido" aparece momentaneamente. (Ele é descartado automaticamente após uma fração de segundo).
michaelhanson
usar um iframe para carga appurle weburlpoderia resolver seu problema
zyanlu
1
@zyanlu: eu tentei com o iFrame. bt ainda safari está mostrando o mesmo erro.
kunjus
5

Se você adicionar um iframe em sua página da Web com o srcesquema definido como personalizado para o seu aplicativo, o iOS será redirecionado automaticamente para esse local no aplicativo. Se o aplicativo não estiver instalado, nada acontecerá. Isso permite que você faça o link direto para o aplicativo, se estiver instalado, ou redirecione para a App Store, se não estiver instalado.

Por exemplo, se você tiver o aplicativo do twitter instalado e navegue para uma página da Web que contenha a seguinte marcação, você será direcionado imediatamente para o aplicativo.

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

Aqui está um exemplo mais completo que redireciona para a App Store se o aplicativo não estiver instalado:

<!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
fonte
O problema com o seu primeiro exemplo é que, se você voltar ao Mobile Safari, ele exibirá "O aplicativo do Twitter não está instalado" mesmo que o Twitter tenha sido iniciado. Mesmo com o segundo exemplo, exibindo "Conteúdo do site". É necessário haver um código que faça algo diferente (carrega outro URL ou exibe uma das duas mensagens) se o aplicativo estiver instalado.
mahboudz
1
Sim, @mahboudz, se você ler o texto, é apenas um exemplo simples para mostrar que é possível redirecionar automaticamente para o aplicativo.
q0rban
Em seguida, segui com um exemplo mais completo que mostraria o conteúdo real do site. Eu posso excluir o texto "O aplicativo do Twitter não está instalado" se isso for mais claro.
Q0rban
iOS 6 ainda displayes pop-up que a página não pode ser aberto por causa da url inválido
Andrei Shender
@AndreiShender, aqui estão as estatísticas de uso do iOS no momento da redação deste documento: monosnap.com/image/8eXUcpEUi8fm94DiMZIdiIp4xUNaln.png iOS 8: 72%, iOS 7: 25%, versões anteriores: 3%
q0rban
4

Heres uma solução.

Configurar uma sitiação booleana usando desfoque e foco

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

Vincule seu link com um manipulador de cliques jquery que chama algo assim.

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

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

se o aplicativo abrir, perderemos o foco na janela e o timer terminará. caso contrário, não obtemos nada e carregamos o URL usual do facebook.

Dane Macaulay
fonte
Muito obrigado pela sugestão. Estou enfrentando o problema de que o diálogo "iniciar aplicativo externo" parece ser suficiente para que o desfoque desative a sinalização. Isso acontece mesmo se o aplicativo não estiver instalado (por exemplo, ao clicar em um link para iniciar um aplicativo para iPhone em uma área de trabalho). Ideias?
fluxon
2

Até onde eu sei, você não pode fazer com que todo o sistema operacional entenda um http:URL de + domínio. Você só pode registrar novos esquemas (eu uso x-darkslide:no meu aplicativo). Se o aplicativo estiver instalado, o Mobile Safari iniciará o aplicativo corretamente.

No entanto, você precisaria lidar com o caso em que o aplicativo não está instalado com um "Ainda está aqui? Clique neste link para baixar o aplicativo do iTunes". na sua página da web.

Fraser Speirs
fonte
2
Isso não está mais correto: com o iOS9 e as versões recentes do Android, você pode registrar seu aplicativo para escutar determinados httpURLs
severin
0

Verifique o User Agent e, caso seja o Mobile Safari, abra um myprotocol: // URL para (tentativa) para abrir o aplicativo do iPhone e abra o Mobile iTunes para fazer o download do aplicativo, caso a tentativa falhe

Isso me parece uma abordagem razoável, mas acho que você não conseguirá abrir o iTunes para dispositivos móveis como um segundo recurso. Eu acho que você terá que escolher um ou outro - redirecionar para o seu aplicativo ou para o iTunes.

ou seja, se você redirecionar para myprotocol: //, e o aplicativo não estiver no telefone, não terá uma segunda chance de redirecionar para o itunes.

Talvez você possa primeiro redirecionar para uma página de destino (otimizada para iphone) e dar ao usuário a opção de clicar no seu aplicativo ou no iTunes para obtê-lo, caso não o possua. Mas você dependerá do usuário para fazer a coisa certa. (Edit: embora você possa definir um cookie para que seja apenas uma primeira vez?)

frankodwyer
fonte
1
Isto é errado. Se for mostrado um erro que a página não pode ser aberta (aplicativo não instalado), o JS ainda será executado. É por isso que você pode redirecionar para outra solução de fallback.
Erik
0

Ao tentar resolver o problema do pop-up, descobri que a Apple tinha uma maneira de contornar essa preocupação.

De fato, quando você clica neste link , se você instalou o aplicativo, ele é redirecionado para ele; caso contrário, você será redirecionado para a página da web, sem nenhum pop-up.

Titignes
fonte
3
Analisei profundamente como esse link estava funcionando, e o melhor que posso encontrar é que não é uma solução JavaScript. A Apple parece ter registrado um manipulador de URL especial para o aplicativo que não requer um protocolo personalizado e, em vez disso, corresponde a uma string de URL. O link que você envia redireciona imediatamente com um 303 para aqui . Se você enviar esse link em um e-mail para si mesmo, poderá observar que clicar nele exibirá o aplicativo AppStore diretamente, se instalado
Casey
Muito interessante. Você está certo: se eu clicar nele, ele abrirá o aplicativo AppStore, se instalado. Mas se você excluir alguns parâmetros até "feriados", isso será exibido no Safari. A Apple pode registrar um esquema de URL especial ...
Titignes
@Titignes, você poderia elaborar esse caminho para abrir o aplicativo ou página da web. Qual é o padrão para criar um URL desse tipo?
Andrei Shender 02/02