2012-07-10 20 views
40

¿Hay una manera de definir algún tipo de mecanismo de tramitación en Android y IOS que permitiría que haga intercepción alguna de las siguientes:Android/iOS - Custom URI/Protocolo de Manejo

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

I' Me gusta escuchar el protocolo o el host, y abrir una Activity/ViewController correspondiente.

Me gustaría también si estos pudieran ser tan amplios como sea posible. Me imagino que esto será más un problema en iOS, pero idealmente podría hacer clic en cualquiera de esos dos esquemas, como hipervínculos, desde cualquier aplicación. Gmail, Safari, etc.

Respuesta

20

Para iOS, sí, se puede hacer dos cosas:

  1. tengan su aplicación anunciar que puede manejar URL's con un esquema dado.

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

La primera opción es bastante sencilla, y se describe en Implementing Custom URL Schemes. Para que el sistema sepa que su aplicación puede manejar un esquema dado: Info.plist

  • actualización de su aplicación con una entrada CFBundleURLTypes

  • implementar -application:didFinishLaunchingWithOptions: en delegado de la aplicación.

La segunda posibilidad es escribir su propio manejador de protocolo. Esto solo funciona dentro de su aplicación, pero puede usarlo junto con la técnica descrita anteriormente. Utilice el método anterior para obtener el sistema para lanzar su aplicación para una determinada URL, y luego usar un controlador de protocolo URL personalizada dentro de su aplicación para aprovechar el poder del sistema de dirección URL de carga del IOS:

  • Create a su propia subclase de NSURLProtocol.

  • Override +canInitWithRequest: - generalmente 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];

  • Anulación -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 aquí depende en gran medida de lo que estás tratando de implementar. Es común que las aplicaciones de iOS implementen un manejador 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 lo que vale, así es exactamente como funciona PhoneGap en iOS. PhoneGap incluye una subclase NSURLProtocol llamada PGURLProtocol que analiza el esquema de cualquier URL que la aplicación intente cargar y toma el control si es uno de los esquemas que reconoce. El primo de código abierto de PhoneGap es Cordova; puede ser útil echarle un vistazo.

+10

La respuesta aceptada debería realmente abordar toda la cuestión. Tu respuesta no menciona a Android. La pregunta tiene un "y" en negrita. – ToothlessRebel

+6

La pregunta realmente debería haberse dividido en dos preguntas: no hay una forma única de manejar URI personalizados en ambas plataformas. –

74

EDITAR 5/2014, ya que esto parece ser una pregunta popular he añadido muchos detalles de la respuesta:

Android:

Para Android, consulte Intent Filter to Launch My Activity when custom URI is clicked.

utiliza una intención de filtro:

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

Ésta está unida a la actividad que desea que se puso en marcha. 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 pondrá en marcha con el URI transferido en el intento.

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

Si ya se está ejecutando, onNewIntent() será llamado en su actividad, de nuevo con el URI en el intento.

Por último, si por el contrario quiere manejar el protocolo personalizado en la UIWebView alojado dentro de su aplicación nativa, puede utilizar:

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

iOS:

Para iOS, consulte Lauching App with URL (via UIApplicationDelegate's handleOpenURL) working under iOS 4, but not under iOS 3.2.

Define tu esquema de URL a través de Info.llaves plist similar 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> 

a continuación, definir una función de controlador a ser llamado en delegado de la aplicación

- (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 dentro de su aplicación nativa, se puede utilizar 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 +), en su lugar puede utilizar 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); 
} 
+1

Una cosa que descubrí es que Gmail (iOS, la aplicación para Android, web) elimina enlaces no estándar de mensajes de correo electrónico. – dzeikei

+4

@dzeikei utilizamos URLs web que redirigen a las URL de nuestra aplicación personalizada. Como beneficio adicional, podemos vincularlo a nuestro análisis de web/correo electrónico más fácilmente. –

+1

@JasonDenizac Sí, eso es lo que teníamos que hacer también, pero sería una experiencia de usuario más agradable si pudieras evitar pasar por el navegador :) – dzeikei