Подтвердить что ты не робот

Android/iOS - настройка пользовательского URI/протокола

Есть ли способ определить какой-то механизм обработки в Android и iOS, который позволил бы мне перехватить одно из следующих:

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

Я бы хотел "прослушать" протокол или хост и открыть соответствующий Activity/ViewController.

Я бы тоже хотел, если бы они были как можно более широкими. Я предполагаю, что это будет больше проблемой для iOS, но я бы идеально мог щелкнуть любую из этих двух схем, как гиперссылки, из любого приложения. Gmail, Safari и т.д.

4b9b3361

Ответ 1

Для iOS, да, вы можете сделать две вещи:

  • Попросите ваше приложение рекламировать, что он может обрабатывать URL-адрес с помощью данной схемы.

  • Установите обработчик протокола для обработки любой схемы, которая вам нравится.

Первый вариант довольно прост и описан в Внедрение пользовательских схем URL. Чтобы система узнала, что ваше приложение может обрабатывать заданную схему:

  • обновите приложение Info.plist с записью CFBundleURLTypes

  • реализовать -application:didFinishLaunchingWithOptions: в делетете приложения.

Вторая возможность - написать собственный обработчик протокола. Это работает только в вашем приложении, но вы можете использовать его в сочетании с описанной выше методикой. Используйте приведенный выше метод, чтобы заставить систему запускать ваше приложение для заданного URL-адреса, а затем использовать собственный обработчик протокола URL-адресов в вашем приложении, чтобы использовать мощь системы загрузки URL-адресов iOS:

  • Создайте свой собственный подкласс NSURLProtocol.

  • Переопределить +canInitWithRequest: - обычно вы просто смотрите на схему URL и принимаете ее, если она соответствует схеме, которую вы хотите обработать, но вы также можете посмотреть и на другие аспекты запроса.

  • Зарегистрируйте свой подкласс: [MyURLProtocol registerClass];

  • Заменить -startLoading и -stopLoading, чтобы запустить и остановить загрузку запроса соответственно.

Прочтите приведенные выше документы NSURLProtocol для получения дополнительной информации. Уровень сложности здесь во многом зависит от того, что вы пытаетесь реализовать. Для приложений iOS обычно используется собственный обработчик URL-адресов, чтобы другие приложения могли выполнять простые запросы. Реализация вашего собственного HTTP или FTP-обработчика более активно.

Для чего это стоит, именно так работает PhoneGap на iOS. PhoneGap включает подкласс NSURLProtocol под названием PGURLProtocol, который просматривает схему любого URL-адреса, которое приложение пытается загрузить и принимает на себя, если это одна из схем, которые он распознает. PhoneGap open-source cousin Cordova - вам может показаться полезным взглянуть.

Ответ 2

ИЗМЕНИТЬ 5/2014, так как это, кажется, популярный вопрос, я добавил много подробностей к ответу:

Android:

Для Android см. Intent Filter для запуска моей активности при нажатии пользовательского URI.

Вы используете фильтр намерений:

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

это связано с активностью, которую вы хотите запустить. Например:

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

Затем в вашей деятельности, если она не запущена, действие будет запущено с URI, переданным в Intent.

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

Если уже запущено, onNewIntent() будет вызываться в вашей активности, снова с URI в намерении.

Наконец, если вы хотите обрабатывать пользовательский протокол в UIWebView, размещенном в вашем родном приложении, вы можете использовать:

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

IOS:

Для iOS обратитесь к Lauching App с URL-адресом (через handleApenURL от UIApplicationDelegate), работающим под iOS 4, но не под iOS 3.2.

Определите свою схему URL-адресов с помощью ключей Info.plist, похожих на:

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

Затем определите функцию обработчика для вызова в делегате приложения

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

Если вы хотите обрабатывать настраиваемый протокол в 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"]) 
    {
      ...
    }
  }
}

}

Для 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);
}