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

Jos*_*osh 46 android protocols manifest ios custom-url-protocol

有没有办法在Android iOS中定义某种处理机制,允许我拦截以下任何一种:

myapp:///events/3/
- or -
http://myapp.com/events/3/
Run Code Online (Sandbox Code Playgroud)

我想"监听"协议或主机,并打开相应的Activity/ViewController.

如果这些可以尽可能在系统范围内,我也会喜欢.我想这将是iOS上的一个问题,但我理想情况下可以从任何应用程序中点击这两个方案中的任何一个,如超链接.Gmail,Safari等

CSm*_*ith 78

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

安卓:

对于Android,请参阅Intent Filter以在单击自定义URI时启动我的活动.

您使用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" /> 
</intent-filter>
Run Code Online (Sandbox Code Playgroud)

这是附加到您要启动的活动.例如:

<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>
Run Code Online (Sandbox Code Playgroud)

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

Intent intent = getIntent();
Uri openUri = intent.getData();
Run Code Online (Sandbox Code Playgroud)

如果已经运行,则会在您的活动中调用onNewIntent(),同样使用intent中的URI.

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

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

iOS版:

对于iOS,请参阅在iOS 4下工作的带URL的Lauching App(通过UIApplicationDelegate的handleOpenURL),但不能在iOS 3.2下工作.

通过Info.plist键定义您的URL方案,类似于:

<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>
Run Code Online (Sandbox Code Playgroud)

然后定义一个处理函数,以便在您的app委托中调用

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

如果要在本机应用程序中托管的UIWebViews中处理自定义协议,可以使用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"]) 
    {
      ...
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

}

对于WKWebView(iOS8 +),您可以改为使用WKNavigationDelegate和此方法:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

  • @dzeikei我们使用重定向到我们的自定义应用网址的网址.作为奖励,我们可以更轻松地将其与我们的网络/电子邮件分析联系起来. (4认同)

Cal*_*leb 20

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

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

在Android上设置应用链接的工作方式类似.首先,您将设置你的网站(S)和你的应用程序之间的关联,然后您将添加意图过滤器,让你的应用程序拦截试图打开您的应用程序能够处理的URL.

尽管细节明显不同,但两种平台的方法基本相同.它使您能够将应用程序插入到网站内容的显示中,无论应用程序尝试访问该内容.


原始答案:

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

  1. 让你的应用宣传它可以处理给定方案的URL.

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

第一个选项非常简单,并在实现自定义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的开源表兄是科尔多瓦 - 你可能会发现它看起来很有帮助.

  • 接受的答案应该真正解决整个问题.你的答案没有提及Android.问题有一个粗体"和". (10认同)
  • 问题确实应该分为两个问题 - 没有一种方法可以跨两个平台处理自定义URI. (6认同)