web-dev-qa-db-ja.com

Android / iOS-カスタムURI /プロトコル処理

Android and iOSで、次のいずれかを傍受できるようにする何らかの種類の処理メカニズムを定義する方法はありますか?

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

プロトコルまたはホストのいずれかを「リッスン」し、対応するActivity/ViewControllerを開きたいです。

これらが可能な限りシステム全体に及ぶことができれば、私も欲しいです。これはiOSではもっと問題になると思いますが、理想的には、これらの2つのスキームのいずれかをハイパーリンクとして、任意のアプリからクリックできるようになります。 Gmail、Safariなど.

46
Josh

更新:これは非常に古い質問であり、iOSとAndroidの両方で大きく変化しました。以下に元の答えを残しますが、新しいプロジェクトに取り組んでいる人や古いプロジェクトを更新している人は、代わりに両方のプラットフォームでサポートされている deep links の使用を検討してください。

IOSでは、ディープリンクは ユニバーサルリンク と呼ばれます。 Webサイト上にJSONファイルを作成して、Webサイトの一部を指すURLにアプリを関連付ける必要があります。次に、NSUserActivityオブジェクトを受け入れるようにアプリを更新し、指定されたURLに対応するコンテンツを表示するようにアプリを設定します。また、アプリが処理できるURLをリストするアプリに資格を追加する必要があります。使用中、オペレーティングシステムは、サイトから関連付けファイルをダウンロードし、アプリが処理するURLのいずれかを誰かが開こうとしたときにアプリを起動します。

Androidのアプリリンク のセットアップも同様に機能します。最初に、Webサイトとアプリの間に関連付けを設定し、次に intent filters を追加して、アプリが処理できるURLを開こうとする試みをインターセプトできるようにします。

詳細は明らかに異なりますが、アプローチは両方のプラットフォームでほとんど同じです。どのアプリがそのコンテンツにアクセスしようとしても、ウェブサイトのコンテンツの表示にアプリを挿入することができます。


元の答え:

IOSでは、はい、次の2つのことができます。

  1. 特定のスキームでURLを処理できることをアプリに広告してもらいます。

  2. プロトコルハンドラをインストールして、好きなスキームを処理します。

最初のオプションは非常に簡単で、 カスタムURLスキームの実装 で説明されています。アプリが特定のスキームを処理できることをシステムに通知するには:

  • cFBundleURLTypesエントリでアプリのInfo.plistを更新します

  • -application:didFinishLaunchingWithOptions:アプリのデリゲートで。

2番目の可能性は、独自のプロトコルハンドラを記述することです。これはアプリ内でのみ機能しますが、上記の手法と組み合わせて使用​​できます。上記の方法を使用して、特定のURLに対してアプリを起動するシステムを取得し、アプリ内でカスタムURLプロトコルハンドラーを使用して、iOSのURL読み込みシステムの能力を活用します。

  • NSURLProtocol の独自のサブクラスを作成します。

  • オーバーライド+canInitWithRequest:-通常、URLスキームを調べて、処理したいスキームと一致する場合はそれを受け入れますが、リクエストの他の側面も見ることができます。

  • サブクラスを登録します:[MyURLProtocol registerClass];

  • オーバーライド-startLoadingおよび-stopLoadingは、それぞれリクエストの読み込みを開始および停止します。

詳細については、上記のリンクのNSURLProtocolドキュメントをお読みください。ここでの難易度は、実装しようとしているものに大きく依存します。 iOSアプリでは、他のアプリが簡単なリクエストを行えるようにカスタムURLハンドラーを実装するのが一般的です。独自のHTTPまたはFTPハンドラーの実装は、もう少し複雑です。

価値があるのは、これがまさにPhoneGapがiOSで機能する方法です。 PhoneGapには、PGURLProtocolというNSURLProtocolサブクラスが含まれています。このサブクラスは、アプリがロードしようとするURLのスキームを調べ、認識しているスキームの1つである場合に引き継ぎます。 PhoneGapのオープンソースのいとこは Cordova -見てみると役に立つかもしれません。

20
Caleb

編集5/2014、これは人気のある質問のように思われるので、答えに多くの詳細を追加しました:

Android:

Androidの場合、 カスタム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 = 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の場合、 iOS 3.2ではなくiOS 4で動作するURLを使用したアプリの起動(UIApplicationDelegateのhandleOpenURL経由) を参照してください。

次のような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>

次に、アプリのデリゲートで呼び出されるハンドラー関数を定義します

- (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);
}
78
CSmith

質問の2番目のオプション:

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

IOS 9では、Universal Linksと呼ばれる新しい手法が導入されました。これにより、https://の場合、Webサイトへのリンクをインターセプトできます。

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

1