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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11421048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:21:18  来源:igfitidea点击:

Android / iOS - Custom URI / Protocol Handling

androidiosprotocolsmanifestcustom-url-protocol

提问by Josh

Is there a way to define some kind of handling mechanism in Android andiOS that would allow me to do intercept either of the following:

有没有办法在 AndroidiOS 中定义某种处理机制,让我可以拦截以下任一项:

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

I'd like to 'listen' for either the protocol or the host, and open a corresponding Activity / ViewController.

我想“监听”协议或主机,并打开相应的 Activity/ViewController。

I'd like too if these could be as system wide as possible. I imagine this will be more of an issue on iOS, but I'd ideally be able to click either of those two schemes, as hyperlinks, from any app. Gmail, Safari, etc.

我也希望这些可以尽可能地覆盖整个系统。我想这在 iOS 上会更严重,但我最好能够从任何应用程序中单击这两种方案中的任何一种,作为超链接。Gmail、Safari 等

采纳答案by Caleb

Update:This is a very old question, and things have changed a lot on both iOS and Android. I'll leave the original answer below, but anyone working on a new project or updating an old one should instead consider using deep links, which are supported on both platforms.

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

On iOS, deep links are called universal links. You'll need to create a JSON file on your web site that associates your app with URLs that point to parts of your web site. Next, update your app to accept a NSUserActivityobject and set up the app to display the content that corresponds to the given URL. You also need to add an entitlement to the app listing the URLs that the app can handle. In use, the operating system takes care of downloading the association file from your site and starting your app when someone tries to open one of the URLs your app handles.

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

Setting up app links on Androidworks similarly. First, you'll set up an association between your web site(s) and your app, and then you'll add intent filtersthat let your app intercept attempts to open the URLs that your app can handle.

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

Although the details are obviously different, the approach is pretty much the same on both platforms. It gives you the ability to insert your app into the display of your web site's content no matter what app tries to access that content.

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



Original answer:

原答案:

For iOS, yes, you can do two things:

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

  1. Have your app advertise that it can handle URL's with a given scheme.

  2. Install a protocol handler to handle whatever scheme you like.

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

  2. 安装一个协议处理程序来处理你喜欢的任何方案。

The first option is pretty straightforward, and described in Implementing Custom URL Schemes. To let the system know that your app can handle a given scheme:

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

  • update your app's Info.plist with a CFBundleURLTypes entry

  • implement -application:didFinishLaunchingWithOptions:in your app delegate.

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

  • 实现-application:didFinishLaunchingWithOptions:在应用程序委托。

The second possibility is to write your own protocol handler. This works only within your app, but you can use it in conjunction with the technique described above. Use the method above to get the system to launch your app for a given URL, and then use a custom URL protocol handler within your app to leverage the power of iOS's URL loading system:

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

  • Create a your own subclass of NSURLProtocol.

  • Override +canInitWithRequest:-- usually you'll just look at the URL scheme and accept it if it matches the scheme you want to handle, but you can look at other aspects of the request as well.

  • Register your subclass: [MyURLProtocol registerClass];

  • Override -startLoadingand -stopLoadingto start and stop loading the request, respectively.

  • 创建您自己的NSURLProtocol.

  • 覆盖+canInitWithRequest:——通常您只需要查看 URL 方案并在它与您要处理的方案匹配时接受它,但您也可以查看请求的其他方面。

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

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

Read the NSURLProtocol docs linked above for more information. The level of difficulty here depends largely on what you're trying to implement. It's common for iOS apps to implement a custom URL handler so that other apps can make simple requests. Implementing your own HTTP or FTP handler is a bit more involved.

阅读上面链接的 NSURLProtocol 文档以获取更多信息。这里的难度在很大程度上取决于您尝试实施的内容。iOS 应用程序通常会实现自定义 URL 处理程序,以便其他应用程序可以发出简单的请求。实现您自己的 HTTP 或 FTP 处理程序涉及更多。

For what it's worth, this is exactly how PhoneGap works on iOS. PhoneGap includes an NSURLProtocol subclass called PGURLProtocol that looks at the scheme of any URL the app tries to load and takes over if it's one of the schemes that it recognizes. PhoneGap's open-source cousin is Cordova-- you may find it helpful to take a look.

就其价值而言,这正是 PhoneGap 在 iOS 上的工作方式。PhoneGap 包含一个名为 PGURLProtocol 的 NSURLProtocol 子类,它查看应用程序尝试加载的任何 URL 的方案,如果它是它识别的方案之一,则接管。PhoneGap 的开源表亲是Cordova——您可能会发现看一看会有所帮助。

回答by CSmith

EDIT 5/2014, as this seems to be a popular question I've added much detail to the answer:

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

Android:

安卓:

For Android, refer to Intent Filter to Launch My Activity when custom URI is clicked.

对于 Android,请参阅Intent Filter to Launch My Activity when custom URI is clicked

You use an 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>

this is attached to the Activity that you want launched. For example:

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

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

Then, in your activity, if not running, the activity will be launched with the URI passed in the Intent.

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

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

If already running, onNewIntent() will be called in your activity, again with the URI in the intent.

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

Lastly, if you instead want to handle the custom protocol in UIWebView's hosted within your native app, you can use:

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

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

iOS:

IOS:

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

对于 iOS,请参阅在 iOS 4 下使用 URL(通过 UIApplicationDelegate 的 handleOpenURL)启动应用程序,但不在 iOS 3.2 下

Define your URL scheme via Info.plist keys similar to:

通过类似于以下内容的 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>

Then define a handler function to get called in your app delegate

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

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

If you want to handle the custom protocol in UIWebViewshosted within your native app, you can use the UIWebViewDelegate method:

如果您想处理原生应用程序中托管的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"]) 
    {
      ...
    }
  }
}

}

}

For WKWebView(iOS8+), you can instead use a WKNavigationDelegate and this method:

对于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);
}

回答by Gregory Cosmo Haun

For the second option in your question:

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

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

There was a new technique introduced with iOS 9, called Universal Links which allows you to intercept links to your website, if they are https://

iOS 9 引入了一项新技术,称为通用链接,它允许您拦截指向您网站的链接,如果它们是 https://

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

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