web-dev-qa-db-fra.com

Android / iOS - Gestion des URI / protocoles personnalisés

Existe-t-il un moyen de définir une sorte de mécanisme de gestion dans Android et iOS qui me permettrait de faire l'interception de l'un des éléments suivants:

myapp:///events/3/
- or -
http://myapp.com/events/3/

Je voudrais "écouter" le protocole ou l'hôte et ouvrir un Activity/ViewController correspondant.

J'aimerais aussi que ceux-ci soient aussi larges que possible à l'échelle du système. J'imagine que ce sera plus un problème sur iOS, mais je serais idéalement en mesure de cliquer sur l'un de ces deux schémas, sous forme de liens hypertexte, à partir de n'importe quelle application. Gmail, Safari, etc.

46
Josh

Mise à jour: C'est une très vieille question, et les choses ont beaucoup changé sur iOS et Android. Je vais laisser la réponse d'origine ci-dessous, mais toute personne travaillant sur un nouveau projet ou mettant à jour un ancien devrait plutôt envisager d'utiliser liens profonds , qui sont pris en charge sur les deux plates-formes.

Sur iOS, les liens profonds sont appelés liens universels . Vous devrez créer un fichier JSON sur votre site Web qui associe votre application à des URL pointant vers des parties de votre site Web. Ensuite, mettez à jour votre application pour accepter un objet NSUserActivity et configurez l'application pour afficher le contenu qui correspond à l'URL donnée. Vous devez également ajouter un droit à l'application répertoriant les URL que l'application peut gérer. En cours d'utilisation, le système d'exploitation prend en charge le téléchargement du fichier d'association à partir de votre site et le démarrage de votre application lorsque quelqu'un essaie d'ouvrir l'une des URL gérées par votre application.

La configuration liens d'application sur Android fonctionne de la même manière. Tout d'abord, vous allez configurer une association entre vos sites Web et votre application, puis vous ajouterez filtres d'intention qui permettent à votre application d'intercepter les tentatives d'ouverture des URL que votre application peut gérer .

Bien que les détails soient évidemment différents, l'approche est à peu près la même sur les deux plates-formes. Il vous donne la possibilité d'insérer votre application dans l'affichage du contenu de votre site Web, quelle que soit l'application qui tente d'accéder à ce contenu.


Réponse originale:

Pour iOS, oui, vous pouvez faire deux choses:

  1. Demandez à votre application d'annoncer qu'elle peut gérer les URL avec un schéma donné.

  2. Installez un gestionnaire de protocole pour gérer le schéma que vous souhaitez.

La première option est assez simple et décrite dans Implémentation de schémas d'URL personnalisés . Pour indiquer au système que votre application peut gérer un schéma donné:

  • mettre à jour Info.plist de votre application avec une entrée CFBundleURLTypes

  • mettre en place -application:didFinishLaunchingWithOptions: dans le délégué de votre application.

La deuxième possibilité consiste à écrire votre propre gestionnaire de protocole. Cela ne fonctionne que dans votre application, mais vous pouvez l'utiliser en conjonction avec la technique décrite ci-dessus. Utilisez la méthode ci-dessus pour que le système lance votre application pour une URL donnée, puis utilisez un gestionnaire de protocole d'URL personnalisé dans votre application pour tirer parti de la puissance du système de chargement d'URL d'iOS:

  • Créez votre propre sous-classe de NSURLProtocol .

  • Passer outre +canInitWithRequest: - en général, vous examinerez simplement le schéma d'URL et l'accepterez s'il correspond au schéma que vous souhaitez gérer, mais vous pouvez également examiner d'autres aspects de la demande.

  • Enregistrez votre sous-classe: [MyURLProtocol registerClass];

  • Passer outre -startLoading et -stopLoading pour démarrer et arrêter le chargement de la demande, respectivement.

Lisez les documents NSURLProtocol liés ci-dessus pour plus d'informations. Le niveau de difficulté ici dépend en grande partie de ce que vous essayez de mettre en œuvre. Il est courant que les applications iOS implémentent un gestionnaire d'URL personnalisé afin que d'autres applications puissent faire des demandes simples. L'implémentation de votre propre gestionnaire HTTP ou FTP est un peu plus complexe.

Pour ce que ça vaut, c'est exactement comment PhoneGap fonctionne sur iOS. PhoneGap comprend une sous-classe NSURLProtocol appelée PGURLProtocol qui examine le schéma de toute URL que l'application essaie de charger et prend le relais s'il s'agit d'un des schémas qu'il reconnaît. Le cousin open-source de PhoneGap est Cordova - vous pouvez trouver utile de jeter un œil.

20
Caleb

EDIT 5/2014, car cela semble être une question populaire, j'ai ajouté beaucoup de détails à la réponse:

Android:

Pour Android, reportez-vous à Filtre d'intention pour lancer mon activité lorsque l'URI personnalisé est cliqué .

Vous utilisez un filtre d'intention:

<intent-filter>
  <action Android:name="Android.intent.action.VIEW" /> 
  <category Android:name="Android.intent.category.DEFAULT" /> 
  <category Android:name="Android.intent.category.BROWSABLE" /> 
  <data Android:scheme="myapp" /> 
</intent-filter>

ceci est attaché à l'activité que vous souhaitez lancer. Par exemple:

<activity Android:name="com.MyCompany.MyApp.MainActivity" Android:label="@string/app_name">
  <intent-filter>
      <action Android:name="Android.intent.action.MAIN" />
      <category Android:name="Android.intent.category.LAUNCHER" />
  </intent-filter>
  <intent-filter>
      <action Android:name="Android.intent.action.VIEW" />
      <category Android:name="Android.intent.category.DEFAULT" />
      <category Android:name="Android.intent.category.BROWSABLE" /> 
      <data Android:scheme="myapp" Android:Host="com.MyCompany.MyApp" />
  </intent-filter>
</activity>

Ensuite, dans votre activité, si elle n'est pas en cours d'exécution, l'activité sera lancée avec l'URI transmis dans l'intention.

Intent intent = getIntent();
Uri openUri = intent.getData();

S'il est déjà en cours d'exécution, onNewIntent () sera appelé dans votre activité, toujours avec l'URI dans l'intention.

Enfin, si vous souhaitez gérer le protocole personnalisé dans UIWebView hébergé dans votre application native, vous pouvez utiliser:

myWebView.setWebViewClient(new WebViewClient()
{
 public Boolean shouldOverrideUrlLoading(WebView view, String url)
 {
  // inspect the url for your protocol
 }
});

iOS:

Pour iOS, reportez-vous à Lauching App with URL (via UIApplicationDelegate's handleOpenURL) fonctionnant sous iOS 4, mais pas sous iOS 3.2 .

Définissez votre schéma d'URL via des clés Info.plist similaires à:

<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLName</key>
            <string>com.yourcompany.myapp</string>
        </dict>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>myapp</string>
            </array>
        </dict>
    </array>

Ensuite, définissez une fonction de gestionnaire pour être appelé dans votre délégué d'application

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
 // parse and validate the URL
}

Si vous souhaitez gérer le protocole personnalisé dans UIWebViews hébergé dans votre application native, vous pouvez utiliser la méthode UIWebViewDelegate:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
 NSURL *urlPath = [request URL];
 if (navigationType == UIWebViewNavigationTypeLinkClicked)
 {
    // inspect the [URL scheme], validate
    if ([[urlPath scheme] hasPrefix:@"myapp"]) 
    {
      ...
    }
  }
}

}

Pour WKWebView (iOS8 +), vous pouvez utiliser à la place un WKNavigationDelegate et cette méthode:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
 NSURL *urlPath = navigationAction.request.URL;  
 if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
 {
   // inspect the [URL scheme], validate
   if ([[urlPath scheme] hasPrefix:@"myapp"])
   {
    // ... handle the request
    decisionHandler(WKNavigationActionPolicyCancel);
    return;
   }
 }

 //Pass back to the decision handler
 decisionHandler(WKNavigationActionPolicyAllow);
}
78
CSmith

Pour la deuxième option de votre question:

http://myapp.com/events/3/

Il y avait une nouvelle technique introduite avec iOS 9, appelée Universal Links qui vous permet d'intercepter les liens vers votre site Web, s'ils sont https: //

https://developer.Apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html

1
Gregory Cosmo Haun