Android / iOS - Manejo personalizado de URI / Protocolo


¿Hay una manera de definir algún tipo de mecanismo de manejo en Android y iOS que me permita interceptar cualquiera de los siguientes:

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

Me gustaría 'escuchar' el protocolo o el host, y abrir una Actividad / ViewController correspondiente.

Me gustaría también si estos pudieran ser lo más amplio posible del sistema. Me imagino que esto será más de un problema en iOS, pero lo ideal sería poder hacer clic en cualquiera de esos dos esquemas, como hipervínculos, desde cualquier aplicación. Gmail, Safari, etc.

Author: qub1n, 2012-07-11

3 answers

Actualización: Esta es una pregunta muy antigua, y las cosas han cambiado mucho tanto en iOS como en Android. Dejaré la respuesta original a continuación, pero cualquiera que trabaje en un nuevo proyecto o actualice uno antiguo debería considerar usar deep links, que son compatibles con ambas plataformas.

En iOS, los enlaces profundos se llaman enlaces universales. Deberá crear un archivo JSON en su sitio web que asocie su aplicación con direcciones URL que apunten a partes de su sitio web. A continuación, actualice su aplicación para aceptar un objeto NSUserActivity y configure la aplicación para mostrar el contenido que corresponde a la URL dada. También debe agregar un derecho a la aplicación que enumere las URL que la aplicación puede manejar. En uso, el sistema operativo se encarga de descargar el archivo de asociación de su sitio e iniciar su aplicación cuando alguien intenta abrir una de las URL que maneja su aplicación.

Configurar enlaces de aplicaciones en Android funciona de manera similar. Primero, crearás una asociación entre tu(s) sitio (s) web y tu aplicación, y luego agregarás filtros de intención que permiten que tu aplicación intercepte los intentos de abrir las URL que tu aplicación puede manejar.

Aunque los detalles son obviamente diferentes, el enfoque es más o menos el mismo en ambas plataformas. Le da la posibilidad de insertar su aplicación en la pantalla del contenido de su sitio web sin importar qué aplicación intente acceder a ese contenido.


Respuesta original:

Para iOS, sí, puedes haga dos cosas:

  1. Haz que tu app anuncie que puede manejar URL con un esquema determinado.

  2. Instale un controlador de protocolo para manejar cualquier esquema que desee.

La primera opción es bastante sencilla, y se describe en Implementando Esquemas de URL personalizados. Para que el sistema sepa que su aplicación puede manejar un esquema determinado:

  • Actualiza la información de tu app.plist con un CFBundleURLTypes entrada

  • Implemente -application:didFinishLaunchingWithOptions: en su delegado de aplicación.

La segunda posibilidad es escribir su propio controlador de protocolo. Esto solo funciona dentro de su aplicación, pero puede usarlo junto con la técnica descrita anteriormente. Usa el método anterior para que el sistema inicie tu aplicación para una URL determinada y, a continuación, usa un controlador de protocolo de URL personalizado dentro de tu aplicación para aprovechar la potencia del sistema de carga de URL de iOS:

  • Crea tu propia subclase de NSURLProtocol.

  • Override +canInitWithRequest: usually por lo general, solo verá el esquema de URL y lo aceptará si coincide con el esquema que desea manejar, pero también puede ver otros aspectos de la solicitud.

  • Registra tu subclase: [MyURLProtocol registerClass];

  • Reemplazar -startLoading y -stopLoading para iniciar y detener la carga de la solicitud, respectivamente.

Lea los documentos de NSURLProtocol vinculados anteriormente para obtener más información. El nivel de dificultad depende en gran medida en lo que está tratando de implementar. Es común que las aplicaciones de iOS implementen un controlador de URL personalizado para que otras aplicaciones puedan realizar solicitudes simples. Implementar su propio controlador HTTP o FTP es un poco más complicado.

Por si sirve de algo, así es exactamente como funciona PhoneGap en iOS. PhoneGap incluye una subclase NSURLProtocol llamada PGURLProtocol que mira el esquema de cualquier URL que la aplicación intenta cargar y se hace cargo si es uno de los esquemas que reconoce. Código abierto de PhoneGap cousin is Cordova you usted puede encontrar útil echar un vistazo.

 19
Author: Caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-08 12:31:45

EDIT 5/2014, como esta parece ser una pregunta popular, he agregado muchos detalles a la respuesta:

Android:

Para Android, consulta Filtro de Intents para Iniciar Mi Actividad cuando se haga clic en URI personalizado.

Se utiliza un filtro de intención:

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

Esto se adjunta a la actividad que desea lanzar. Por ejemplo:

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

Luego, en su actividad, si no se está ejecutando, la actividad se iniciará con el URI pasado en la Intent.

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

Si ya se está ejecutando, se llamará a onNewIntent() en tu actividad, de nuevo con el URI en la intent.

Por último, si en su lugar desea manejar el protocolo personalizado en UIWebView alojado dentro de su aplicación nativa, puede usar:

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

IOS:

Para iOS, consulte Aplicación Lauching con URL (a través de UIApplicationDelegate handleOpenURL) que funciona bajo iOS 4, pero no bajo iOS 3.2.

Defina su esquema de URL a través de Info.llaves de plist similares a:

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

Luego define una función de controlador para que te llamen en tu delegado de app

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

Si desea manejar el protocolo personalizado en UIWebViews alojado en su aplicación nativa, puede usar el método 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"]) 
    {
      ...
    }
  }
}

}

Para WKWebView (iOS8+), puede usar un WKNavigationDelegate y este método:

- (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);
}
 75
Author: CSmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:37

Para la segunda opción en su pregunta:

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

Se introdujo una nueva técnica con iOS 9, llamada Enlaces Universales, que le permite interceptar enlaces a su sitio web, si son https: / /

Https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html

 1
Author: Gregory Cosmo Haun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-20 17:46:42