2010-12-08

アプリを開くリンク #1 - 内部リンクの置き換えのために (MacBloggerGlass)

以前の記事で、内部リンクの置き換えを実現するためには記事内容をファイルとしてローカルのストレージに書き出すしかないかも、と書いた(→「記事の表示機能を作る (MacBloggerGlass)」)。ここ数日、Cocoa Bindings の使い方をあれこれ調べる間もそのことについて考え続けてきた。今日になって、「あれ、そう言えば iTunes Store のリンクって Safari から iTunes に飛ぶよな」と気付いた。

たとえば、以下のリンクは「itms://」で始まる URL で、Safari でクリックすれば iTunes.app で Coldplay の新曲(2010-12-08 時点)のページが開く(Mac と iPad で確認)。

itms://itunes.apple.com/jp/album/christmas-lights-single/id406970808

ちなみに、Safari 以外のブラウザだと、iTunes.app を開く前に確認のダイアログが現れる。右のスクリーンショットは Google Chrome でこのリンクをクリックしたときに出てくるものだ。

Safari (つまり WebView) でリンクをクリックしてアプリに通知させることができるなら、内部リンクをそれで置き換えれば良い。そうすれば MacBloggerGlass (以下、MBG) から、MBG 自身に開きたい記事の情報を伝えることができる。フィードデータから記事ごとに HTML ファイルを作って書き出して、file:/// でアクセスするよりもスマートだ。

もっとも、MBG を作る動機にもなっている「オフラインでも読める」ようにするためには、記事の内容をふくめたフィードデータをローカルに保存しなくてはならないんだけど。

ともあれ、これで方向性が定まった。まずは「アプリを開くリンク」について調べるところからだ。

itms:// を開こうとしたとき、誰が iTunes を起動するのか?

では、特定の URI スキーム (http://... の http の部分) とそれを扱うアプリの組み合わせを知っているのは誰だろう? Safari のようなブラウザ自身だろうか? 少なくとも Mac OS X では(おそらく iOS でも) 専用のサービス (API) が用意されている。

(「Launch Services Programming Guide: Introduction」より)
Launch Services is an API that enables a running application to open other applications or their document files or URLs (uniform resource locators) in a way similar to the Finder or the Dock. Using Launch Services, an application can perform such tasks as:

  • Open (launch or activate) another application
  • Open a document or a URL in another application
  • Identify the preferred application for opening a given document or URL
  • [...snip...]

この Launch Services がドキュメントのタイプや URL タイプとアプリの組み合わせを保持している。では、Launch Services はその組み合わせの情報をどこから得るのか? それはアプリが持っている Info.plist の記述からだ。

具体的には、Info.plist 中の CFBundleURLTypes にアプリが開くことのできる URL タイプが記述されている。

Property List の書き方

Info.plist は Property List と呼ばれる XML 形式で記述する。以下に Xcode が作るデフォルトの Info.plist を示す。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>CFBundleDevelopmentRegion</key>
 <string>English</string>
 <key>CFBundleExecutable</key>
 <string>${EXECUTABLE_NAME}</string>
 <key>CFBundleIconFile</key>
 <string></string>
 <key>CFBundleIdentifier</key>
 <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
 <key>CFBundleInfoDictionaryVersion</key>
 <string>6.0</string>
 <key>CFBundleName</key>
 <string>${PRODUCT_NAME}</string>
 <key>CFBundlePackageType</key>
 <string>APPL</string>
 <key>CFBundleShortVersionString</key>
 <string>1.0</string>
 <key>CFBundleSignature</key>
 <string>????</string>
 <key>CFBundleVersion</key>
 <string>1</string>
 <key>LSMinimumSystemVersion</key>
 <string>${MACOSX_DEPLOYMENT_TARGET}</string>
 <key>NSMainNibFile</key>
 <string>MainMenu</string>
 <key>NSPrincipalClass</key>
 <string>NSApplication</string>
</dict>
</plist>

URL タイプは、トップレベルにある dict 要素の子として記述する。つまり、CFBundleExecutable などと同じレベルの要素にする。その際、CFBundleURLTypes が dict の array になるように構成する。そして、各 dict の中身には以下の 4 つの要素を置く。

CFBundleURLType 内の要素 (「Launch Services Programming Guide」より)
Key Type Description
CFBundleTypeRole string アプリがドキュメントをどのように扱うものなのか。Launch Services が認識するのは Editor、Viewer、そして None の 3 つのみ。
CFBundleURLName string URL タイプの名前
CFBundleURLIconFile string このタイプの URL を表示する際に使われるアイコンファイルの名前
CFBundleURLSchemes array このタイプにふくまれる URL のスキームの配列。各スキームは string として記述する。

典型的な CFBundleURLTypes の構造は以下のようになる。

CFBundleURLTypes
+-- array
    +-- dict
    |   +-- CFBundleTypeRole
    |   |   +-- string
    |   +-- CFBundleURLName
    |   |   +-- string
    |   +-- CFBundleURLIconFile
    |   |   +-- string
    |   +-- CFBundleURLSchemes
    |       +-- array
    |           +-- string
    |           +-- string
    |           ...
    +-- dict
        ...

iTunes.app の Info.plist を覗いてみると、CFBundleURLIconFile は省略しても構わないようだ。

以下のスクリーンショットは、実際に Xcode 中で Info.plist を編集し、URL タイプを 1 つ、追加したところのものだ。

Info.plist に URL タイプを追加する様子
左に表示されている要素の種類はドロップダウンリストの中から選ぶことができる。トップレベルで URL Types を選ぶとその子要素の構造も同時に作られる(デフォルトでは URL Identifier だけが追加されている)。この例では URI スキームとして sample という文字列を指定している。

アプリ側での作り込み

Launch Services はアプリに対してアプリの起動や URL を開く等の Apple イベントを送ってくる。つまり、アプリは送られてきたイベントを適切に処理することができなければならない。

そのためにはどういうコードを書けば良いのか? それは次回の記事で(ドキュメントは見つけてあるがまだ読んでいない→「Cocoa Scripting Guide: How Cocoa Applications Handle Apple Events」)。

関連リンク

関連記事

0 件のコメント:

コメントを投稿