49 votes

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

Juste une petite question. Existe-t-il un moyen de définir une sorte de mécanisme de traitement dans Android et iOS qui me permettrait d'intercepter l'un ou l'autre des éléments suivants :

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

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

J'aimerais aussi qu'ils soient aussi étendus que possible au système. J'imagine que ce sera davantage un problème sur iOS, mais l'idéal serait de pouvoir cliquer sur l'un de ces deux schémas, en tant qu'hyperliens, à partir de n'importe quelle application. Gmail, Safari, etc.

78voto

CSmith Points 6083

EDIT 5/2014, comme 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'on clique sur un URI personnalisé .

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>

il est attaché à l'activité que vous voulez 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 plutôt gérer le protocole personnalisé dans les UIWebViews hébergés 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 à Lancement d'une application avec une URL (via handleOpenURL de UIApplicationDelegate) 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>

Définissez ensuite une fonction de gestion qui sera appelée 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 voulez 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 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;
   }
 }

 decisionHandler(WKNavigationActionPolicyAllow);
}

1 votes

J'ai découvert que GMail (application iOS, application Android, web) supprime les liens non standard des e-mails.

4 votes

@dzeikei nous utilisons des URLs web qui redirigent vers nos urls d'applications personnalisées. En prime, nous pouvons les relier plus facilement à nos analyses web/email.

1 votes

@JasonDenizac Oui, c'est ce que nous avons dû faire également mais l'expérience utilisateur serait plus agréable si vous pouviez éviter de passer par le navigateur :)

24voto

Caleb Points 72897

Pour iOS, oui, vous pouvez faire deux choses :

  1. Faites en sorte que votre application annonce qu'elle peut traiter les URL avec un schéma donné.

  2. Installez un gestionnaire de protocole pour gérer le schéma de votre choix.

La première option est assez simple et décrite dans le document Mise en œuvre de schémas d'URL personnalisés . Pour faire savoir au système que votre application peut gérer un schéma donné :

  • mettez à jour le fichier Info.plist de votre application en y ajoutant une entrée CFBundleURLTypes.

  • mettre en œuvre -application:didFinishLaunchingWithOptions: dans votre délégué d'application.

La deuxième possibilité est d'é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 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 .

  • Remplacer +canInitWithRequest: -- En général, on se contente de regarder le schéma de l'URL et on l'accepte s'il correspond au schéma que l'on veut gérer, mais on peut aussi regarder d'autres aspects de la demande.

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

  • Remplacer -startLoading et -stopLoading pour démarrer et arrêter le chargement de la requête, respectivement.

Pour plus d'informations, lisez les documents relatifs au protocole NSURLP dont le lien figure ci-dessus. Le niveau de difficulté dépend largement de ce que vous essayez de mettre en œuvre. Il est courant pour les applications iOS de mettre en œuvre un gestionnaire d'URL personnalisé afin que d'autres applications puissent effectuer des requêtes simples. La mise en œuvre de votre propre gestionnaire HTTP ou FTP est un peu plus complexe.

Pour ce que ça vaut, c'est exactement comme ça que PhoneGap fonctionne sur iOS. PhoneGap comprend une sous-classe NSURLProtocol appelée PGURLProtocol qui examine le schéma de toute URL que l'application tente de charger et prend le relais s'il s'agit de l'un des schémas qu'elle reconnaît. Le cousin open-source de PhoneGap est Cordova -- Vous trouverez peut-être utile d'y jeter un coup d'œil.

10 votes

La réponse acceptée doit vraiment répondre à l'ensemble de la question. Votre réponse ne fait aucune mention d'Android. La question comporte un "et" en gras.

6 votes

La question aurait dû être divisée en deux : il n'y a pas une seule façon de gérer les URI personnalisés sur les deux plateformes.

1voto

Pour la deuxième option de votre question :

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

Une nouvelle technique a été 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X