Czy można zarejestrować schemat adresu URL oparty na domenie http + dla aplikacji na iPhone'a, takich jak YouTube i Mapy?


223

Chciałbym mieć iOS do otwierania adresów URL z mojej domeny (np. Http://martijnthe.nl ) z moją aplikacją za każdym razem, gdy aplikacja jest zainstalowana na telefonie, oraz z Mobile Safari, jeśli tak nie jest.

Czytam, że można utworzyć w tym celu unikalny sufiks protokołu i zarejestrować go w Info.plist, ale Mobile Safari wyświetli błąd, jeśli aplikacja nie zostanie zainstalowana.

Co byłoby obejściem?

Jeden pomysł:

1) Użyj adresów URL http: //, które otwierają się w dowolnej przeglądarce na komputerze i wyświetlają usługę za pośrednictwem przeglądarki

2) Sprawdź User-Agent, a jeśli jest to Mobile Safari, otwórz myprotocol: // URL do (próba) otwarcia aplikacji na iPhone'a i niech Mobile iTunes do pobrania aplikacji na wypadek, gdyby próba się nie powiodła

Nie wiesz, czy to zadziała ... sugestie? Dzięki!


4
W metrze w Nowym Jorku jest WiFi przez Boingo, które zapewnia bezpłatny dostęp do Wi-Fi, jeśli pobierzesz polecaną przez nich aplikację. Po pobraniu wrócisz do Safari, a przeglądarka wykryje, czy została zainstalowana, a następnie udzieli ci dostępu. Wiesz, jak to się robi?
TommyG

2
Universal Links obsługuje teraz ten przypadek użycia bez żadnego komunikatu o błędzie. Oto jak skonfigurować domenę i aplikację: blog.branch.io/…
Alex Austin

Odpowiedzi:


243

Myślę, że najmniej inwazyjny sposób to zrobić:

  1. Sprawdź, czy klient użytkownika to iPhone / iPod Touch
  2. Sprawdź appInstalledplik cookie
  3. Jeśli plik cookie istnieje i jest ustawiony na true, ustaw window.locationna your-uri://(lub wykonaj stronę przekierowującą)
  4. Jeśli plik cookie nie istnieje, otwórz „Czy wiesz, że Twoja nazwa witryny ma aplikację na iPhone'a”? modalne z „Tak, już to mam”, „Nie, ale chciałbym spróbować” i „Zostaw mnie w spokoju”.
    1. Przycisk „Tak” ustawia ciasteczko na „prawda” i przekierowuje na your-uri://
    2. Przycisk „Nie” przekierowuje do strony „ http://itunes.com/apps/yourappname ”, która otworzy App Store na urządzeniu
    3. Przycisk „Zostaw mnie w spokoju” ustawia ciasteczko na fałsz i zamyka modal

Inną opcją, w którą grałem, ale okazałem się trochę niezręczny, było wykonanie następujących czynności w 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://";

16
Świetne rozwiązanie. Jeśli twoja awaria dotyczy innej aplikacji, załaduje się NATYCHMIAST bez wyświetlania błędu. Zamiast wracać do itunes.com ... użyj itms: //phobos.apple.com / ..., aby uniknąć błędu wyskakującego okienka!
jb.

47
Problem : Gdy się window.location="custom-uri://powiedzie, limit czasu rezerwowego nie jest zabijany. Gdy użytkownik powróci do przeglądarki z aplikacji, minutnik nadal tam jest i uruchomi link do sklepu z aplikacjami. Jest to słaba wygoda użytkowania.
JoJo

5
Wygląda na to, że pliki cookie są izolowane w # ios6, więc nie można uzyskać dostępu do plików cookie ustawionych przez aplikację z innego. (Na przykład aplikacja WebUI i Safari Mobile)
Olivier Amblet

2
Czy ktoś znalazł sposób, aby zapobiec uruchomieniu pierwotnego limitu czasu, gdy użytkownik powróci do przeglądarki? (wspomniany wyżej problem JoJo wspomina)
cobolstinks

2
Aby rozwiązać problem, o którym wspomina JoJo, uruchom kod tylko w przypadku przekroczenia limitu czasu, jeśli nie upłynęło dużo czasu od kliknięcia łącza przez użytkownika. Zobacz to rozwiązanie: stackoverflow.com/a/14751543/533420
kkara

95

Jest to całkiem możliwe, aby to zrobić w JavaScript, o ile twoja awaria jest kolejnym applink. Opierając się na sugestii Nathana :

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

Sprawdź demo na żywo tutaj .


7
Zgadzam się z Lee, wydaje się to prostszym rozwiązaniem - chociaż nadal pojawia się komunikat o błędzie z safari, jeśli aplikacja nie istnieje i przekierowuje do sklepu z aplikacjami.
Jon

2
Użyłem tego rozwiązania zarówno na Androida, jak i iOS. Przekonałem się, że jeśli zmienię limit czasu z 500 na 100, nie mam wyskakującego okna dialogowego „Nie można otworzyć strony” w iOS. Przekonałem się również, że limit czasu musi wynosić 50 dla Androida
Rossini

14
Użycie „itms-apps:” zamiast „itms:” zapisuje 1 przekierowanie i bezpośrednio otwiera stronę aplikacji w sklepie z aplikacjami.
Niemiecki Latorre

6
@Rossini jest to wbudowane w system Android poprzez ustawienie filtru zamiaru dla działania, który reaguje na konkretnego hosta
jwadsack

9
Czy ktoś wie, jak uniknąć komunikatu o błędzie „nie można otworzyć strony” z safari, jeśli aplikacja nie jest zainstalowana i przed przekierowaniem do sklepu z aplikacjami?
davidk


24

Stwierdziłem, że wybrana odpowiedź działa z aplikacjami przeglądarki, ale miałem problemy z kodem działającym w aplikacjach innych niż przeglądarka, które implementują UIWebView.

Problemem było dla mnie, że użytkownik aplikacji na Twitterze kliknąłby link prowadzący do mojej witryny za pośrednictwem UIWebViewaplikacji na Twitterze. Następnie, kiedy kliknęli przycisk z mojej strony, Twitter próbuje być fantazyjny i wypełnia tylko, window.locationjeśli strona jest dostępna. Więc co się dzieje, jest to UIAlertViewpop up mówiąc, jesteś pewien, że chcesz kontynuować, a następnie od razu przekierowuje do App Store bez drugiego popup.

Moje rozwiązanie dotyczy ramek iframe. Pozwala to uniknąć UIAlertViewprezentacji, zapewniając łatwą i elegancką obsługę.

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

EDYTOWAĆ:

Dodaj pozycję bezwzględną do elementu iframe, aby po wstawieniu na dole strony nie było przypadkowej spacji.

Należy również zauważyć, że nie znalazłem potrzeby takiego podejścia w przypadku Androida. Korzystanie window.location.hrefpowinno działać dobrze.


1
To działa!! Dzięki wreszcie znalazłem rozwiązanie, które działa na każdej przeglądarce.
koleror

2
To najlepsze rozwiązanie, jeśli zostanie znalezione. Dziękuję Ci. Nie ma już wyskakującego okienka błędu.
confile

1
@Tim, jeśli chcesz, aby ten kod był uruchamiany po kliknięciu łącza, to zawiń ten kod w funkcję, która jest wywoływana po kliknięciu łącza.
cnotethegr8,

1
@ cnotethegr8 Włączyłem go w funkcję i przekierowanie do niestandardowego adresu URL działa świetnie, ale powrót do iTunes nie działa. Oto mój kod . czego mi brakuje?
Tim

1
Czy ktoś miał z tym problem w iOS 9. To już nie działa w Safari.
bgolson

20

W iOS9 Apple wreszcie wprowadziło możliwość zarejestrowania aplikacji do obsługi określonych http://adresów URL: Uniwersalne łącza .

Bardzo przybliżone wyjaśnienie, jak to działa:

  • Zgłaszasz zainteresowanie otwieraniem http://adresów URL dla niektórych domen (adresów URL) w swojej aplikacji.
  • Na serwerze określonych domen musisz wskazać, które adresy URL mają zostać otwarte, w której aplikacji zadeklarowano zainteresowanie otwieraniem adresów URL z domeny serwera.
  • Usługa ładowania adresów URL na iOS sprawdza wszystkie próby otwarcia http://adresów URL w celu instalacji, jak wyjaśniono powyżej, i automatycznie otwiera poprawną aplikację, jeśli jest zainstalowana; bez wcześniejszego przeglądania Safari ...

To najczystszy sposób na głębokie linkowanie na iOS, niestety działa tylko w iOS9 i nowszych ...


i nie działa w przeglądarce ... tylko na zewnątrz, na przykład z wiadomości lub notatek
Mihey Mik

9

BUDOWA Ponownie na odpowiedź Nathana i JB:

Jak uruchomić aplikację z adresu URL bez dodatkowego kliknięcia Jeśli wolisz rozwiązanie, które nie zawiera przejściowego kroku kliknięcia łącza, możesz użyć następujących opcji. Za pomocą tego javascript mogłem zwrócić obiekt Httpresponse z Django / Python, który pomyślnie uruchamia aplikację, jeśli jest zainstalowana lub alternatywnie uruchamia sklep z aplikacjami w przypadku przekroczenia limitu czasu. Uwaga: Musiałem także dostosować limit czasu z 500 do 100, aby działał na iPhonie 4S. Przetestuj i popraw, aby dostosować go do swojej sytuacji.

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

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 jest wykrywanie, czy twoja aplikacja jest już wywołana, a bieżąca karta Safari przechodzi do tła, ten kod pochodzi z www.baidu.com


Przetestowałem to rozwiązanie i stwierdziłem, że mimo prawidłowego dostarczania zdarzeń, przez chwilę pojawia się okno dialogowe błędu „Safari nie może otworzyć tej strony, ponieważ adres jest nieprawidłowy”. (Automatycznie zwalnia po ułamku sekundy).
michaelhanson

użyj iframe, aby załadować appurli weburlmoże rozwiązać problem
zyanlu

1
@zyanlu: próbowałem z iFrame. bt nadal safari pokazuje ten sam błąd.
kunjus

5

Jeśli dodasz iframena swojej stronie internetowej z srcniestandardowym schematem dla swojej aplikacji, iOS automatycznie przekieruje do tej lokalizacji w aplikacji. Jeśli aplikacja nie zostanie zainstalowana, nic się nie stanie. Pozwala to na głębokie łącze do aplikacji, jeśli jest zainstalowana, lub przekierowanie do App Store, jeśli nie jest zainstalowana.

Na przykład, jeśli masz zainstalowaną aplikację Twitter i przejdź do strony internetowej zawierającej następujący znacznik, natychmiast zostaniesz przekierowany do aplikacji.

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

Oto dokładniejszy przykład, który przekierowuje do sklepu App Store, jeśli aplikacja nie jest zainstalowana:

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

Problem z pierwszym przykładem polega na tym, że jeśli wrócisz do Mobile Safari, wyświetli się komunikat „Aplikacja Twitter nie jest zainstalowana”, mimo że Twitter został uruchomiony. To samo z drugim przykładem, wyświetlającym „Treść witryny”. Jeśli aplikacja jest zainstalowana, musi istnieć kod, który robi coś innego (ładuje inny adres URL lub wyświetla jeden z dwóch komunikatów).
mahboudz

1
Tak, @mahboudz, jeśli czytasz tekst, to tylko prosty przykład pokazujący, że możliwe jest automatyczne przekierowanie do aplikacji.
q0rban

Następnie podam dokładniejszy przykład, który pokazuje rzeczywistą treść witryny. Mogę usunąć tekst „Aplikacja Twitter nie jest zainstalowana”, jeśli to uczyni jaśniejszym.
q0rban

ios 6 nadal wyświetla wyskakujące okienko Nie można otworzyć tej strony z powodu nieprawidłowego
adresu

@AndreiShender, oto statystyki użytkowania iOS w momencie pisania tego tekstu : monosnap.com/image/8eXUcpEUi8fm94DiMZIdiIp4xUNaln.png iOS 8: 72%, iOS 7: 25%, Wcześniejsze wersje: 3%
q0rban

4

Oto rozwiązanie.

Sytuacja logiczna za pomocą rozmycia i ostrości

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

Powiąż swój link za pomocą procedury obsługi kliknięć jquery, która wywołuje coś takiego.

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

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

jeśli aplikacja się otworzy, stracimy skupienie na oknie i minutnik się skończy. w przeciwnym razie nic nie dostaniemy i załadujemy zwykły adres URL na Facebooku.


Wielkie dzięki za sugestię. Mam do czynienia z problemem, że dialog „uruchom aplikację zewnętrzną” wydaje się wystarczający, aby rozmycie dezaktywowało flagę. Dzieje się tak nawet wtedy, gdy aplikacja nie jest zainstalowana (np. Po kliknięciu linku, który ma uruchomić aplikację iPhone na pulpicie). Pomysły?
fluxon

2

O ile mi wiadomo, nie możesz sprawić, by cały system operacyjny zrozumiał http:adres URL domeny +. Możesz zarejestrować tylko nowe schematy (używam x-darkslide:w mojej aplikacji). Jeśli aplikacja jest zainstalowana, Mobile Safari uruchomi ją poprawnie.

Musisz jednak poradzić sobie z przypadkiem, w którym aplikacja nie jest zainstalowana, z komunikatem „Nadal tu jesteś? Kliknij ten link, aby pobrać aplikację z iTunes”. na twojej stronie internetowej.


2
To już nie jest poprawne: w iOS9 i najnowszych wersjach Androida możesz zarejestrować swoją aplikację, aby nasłuchiwać określonych httpadresów URL
Severin

0

Sprawdź User-Agent, a jeśli jest to Mobile Safari, otwórz myprotocol: // URL do (próba), aby otworzyć aplikację na iPhone'a i niech Mobile iTunes do pobrania aplikacji na wypadek, gdyby próba się nie powiodła

Wydaje mi się to rozsądnym podejściem, ale nie sądzę, że będziesz w stanie uruchomić mobilne iTunes jako drugi ośrodek. Myślę, że będziesz musiał wybrać jedno lub drugie - przekieruj do swojej aplikacji lub iTunes.

tzn. jeśli przekierujesz na myprotocol: //, a aplikacji nie ma na telefonie, nie dostaniesz drugiej szansy na przekierowanie do iTunes.

Być może możesz najpierw przekierować na stronę docelową (zoptymalizowaną dla iPhone'a) i dać użytkownikowi opcję kliknięcia Twojej aplikacji lub iTunes, aby uzyskać aplikację, jeśli jej nie ma? Będziesz jednak polegał na tym, że użytkownik zrobi tam właściwą rzecz. (Edycja: chociaż można ustawić ciasteczko, aby było to po raz pierwszy?)


1
To jest źle. Jeśli zostanie wyświetlony błąd, że strona nie może zostać otwarta (aplikacja nie jest zainstalowana), JS jest nadal wykonywany. Właśnie dlatego możesz przekierować do innego rozwiązania zastępczego.
Erik

0

Próbując rozwiązać problem wyskakujących okienek, odkryłem, że Apple ma rozwiązanie tego problemu.

Rzeczywiście, po kliknięciu tego linku aplikacja zainstalowana zostanie przekierowana na nią; w przeciwnym razie nastąpi przekierowanie na stronę internetową bez wyskakującego okienka.


3
Wgłębiłem się w sposób, w jaki działał ten link, a najlepsze, co mogę wymyślić, to to, że nie jest to wcale JavaScript. Wygląda na to, że Apple zarejestrowało specjalny moduł obsługi adresów URL dla swojej aplikacji, który nie wymaga niestandardowego protokołu i zamiast tego dopasowuje ciąg adresu URL. Link, który wysyłasz, przekierowuje natychmiast z 303 tutaj . Jeśli wyślesz ten link do siebie e-mailem, zauważysz, że kliknięcie go spowoduje bezpośrednie otwarcie aplikacji AppStore, jeśli jest zainstalowana
Casey

Bardzo interesujące. Masz rację: jeśli go kliknę, wyświetli się aplikacja AppStore, jeśli jest zainstalowana. Ale jeśli usuniesz niektóre parametry do „świąt”, pojawi się w Safari. Apple może zarejestrować specjalny schemat adresów URL ...
Titignes,

@Titignes, czy mógłbyś rozwinąć tę drogę, aby otworzyć aplikację lub stronę internetową? Jaki jest wzorzec budowania takiego adresu URL?
Andrei Shender
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.