关于Android / iOS:Android / iOS-自定义URI /协议处理

Android / iOS - Custom URI / Protocol Handling

是否有一种方法可以在Android和iOS中定义某种处理机制,从而允许我截取以下任意一项:

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

我想"监听"协议或主机,然后打开相应的Activity / ViewController。

我也想尽可能将它们扩展到整个系统。我想这将在iOS上成为更多问题,但理想情况下,我希望能够从任何应用程序中单击这两种方案中的任何一种,作为超链接。 Gmail,Safari等。


编辑5/2014,因为这似乎是一个受欢迎的问题,所以我为答案添加了很多细节:

Android:

对于Android,请单击单击自定义URI时,请参阅意图过滤器以启动我的活动。

您使用意图过滤器:

1
2
3
4
5
6
<intent-filter>
   
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="myapp" />
</intent-filter>

此附件附加到您要启动的活动。例如:

1
2
3
4
5
6
7
8
9
10
11
  <intent-filter>
     
      <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
  <intent-filter>
     
      <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>

然后,在您的活动中(如果未运行),将使用在Intent中传递的URI启动活动。

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

如果已经运行,则将在您的活动中调用onNewIntent(),并再次使用该URI。

最后,如果您想在本机应用程序中托管的UIWebView中处理自定义协议,则可以使用:

1
2
3
4
5
6
7
myWebView.setWebViewClient(new WebViewClient()
{
 public Boolean shouldOverrideUrlLoading(WebView view, String url)
 {
  // inspect the url for your protocol
 }
});

iOS:

对于iOS,请参考在iOS 4下工作但具有URL(通过UIApplicationDelegates handleOpenURL)的应用程序,而不是在iOS 3.2下工作。

通过类似于以下内容的Info.plist键定义URL方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
<key>CFBundleURLTypes</key>
   
        <dict>
            <key>CFBundleURLName</key>
            <string>com.yourcompany.myapp</string>
        </dict>
        <dict>
            <key>CFBundleURLSchemes</key>
           
                <string>myapp</string>
            </array>
        </dict>
    </array>

然后定义一个处理程序函数以在您的应用程序委托中调用

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

如果要在本机应用程序中托管的UIWebViews中处理自定义协议,则可以使用UIWebViewDelegate方法:

1
2
3
4
5
6
7
8
9
10
11
12
- (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"])
    {
      ...
    }
  }
}

} ??

对于WKWebView(iOS8),您可以改用WKNavigationDelegate和以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (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);
}


更新:这是一个非常老的问题,iOS和Android上的情况都发生了很大变化。我将在下面保留原始答案,但是从事新项目或更新旧项目的任何人都应该考虑使用深链接,这两个平台都支持。

在iOS上,深层链接称为通用链接。您需要在您的网站上创建一个JSON文件,该文件将您的应用程序与指向您网站的各个部分的URL相关联。接下来,更新您的应用程序以接受NSUserActivity对象,并设置应用程序以显示与给定URL对应的内容。您还需要向应用程序添加权利,列出该应用程序可以处理的URL。在使用中,当有人尝试打开您的应用程序处理的URL之一时,操作系统会负责从您的站点下载关联文件并启动您的应用程序。

在Android上设置应用程序链接的操作与此类似。首先,您将在网站和应用程序之间建立关联,然后添加意图过滤器,以使您的应用程序拦截尝试打开应用程序可以处理的URL的尝试。

尽管细节明显不同,但是两种平台上的方法几乎相同。它使您能够将应用程序插入网站内容的显示中,而不管是什么应用程序尝试访问该内容。

原始答案:

对于iOS,是的,您可以做两件事:

  • 让您的应用广告宣传它可以使用给定的方案处理URL。

  • 安装协议处理程序以处理您喜欢的任何方案。

  • 第一个选项非常简单,在实现自定义URL方案中进行了介绍。让系统知道您的应用程序可以处理给定的方案:

    • 使用CFBundleURLTypes条目更新应用程序的Info.plist

    • 您的应用程序委托中的

      实现-application:didFinishLaunchingWithOptions:

    第二种可能性是编写自己的协议处理程序。这仅在您的应用程序中有效,但是您可以将其与上述技术结合使用。使用上面的方法来使系统启动给定URL的应用程序,然后在应用程序中使用自定义URL协议处理程序来利用iOS URL加载系统的功能:

    • 创建自己的NSURLProtocol子类。

    • 覆盖+canInitWithRequest:-通常,您仅查看URL方案并接受它(如果它与您要处理的方案匹配),但是您也可以查看请求的其他方面。

    • 注册您的子类:[MyURLProtocol registerClass];

    • 重写-startLoading-stopLoading分别开始和停止加载请求。

    阅读上面链接的NSURLProtocol文档以获取更多信息。这里的难易程度在很大程度上取决于您要实现的目标。 iOS应用通常会实现自定义URL处理程序,以便其他应用可以发出简单的请求。实现您自己的HTTP或FTP处理程序要复杂一些。

    对于它的价值,这正是PhoneGap在iOS上的工作方式。 PhoneGap包含一个称为PGURLProtocol的NSURLProtocol子类,该子类查看应用程序尝试加载的任何URL的方案,如果该方案是它可以识别的方案之一,则进行接管。 PhoneGap的开源表弟是Cordova-您可能会发现看一下它很有帮助。


    对于问题中的第二个选项:

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

    iOS 9引入了一项称为通用链接的新技术,如果它们是https://

    ,则可以拦截到您网站的链接。

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