Titanium Mobileで作る! iPhone/Androidアプリ

第17回Intentを使ってみる

前回は開発環境についての解説で終わってしまいましたが、今回からいくつかAndroidに特有な機能を紹介していきます。今回はIntentの受け取りについて解説していきます。

Intentとは

Androidではアプリ間の連携のためにIntentという仕組みが用意されています。正確にはアプリ内でもWindow(本来のAndroidではActivityとよばれます)間の通信にも利用されていますが、Titaniumでは隠蔽されており気づくことがありません。IntentやActivityといった概念はJavaを利用したAndroidアプリ開発では必須の概念なので、一度Android Developersのリファレンスなどの公式資料に目を通しておくとよいでしょう。

では、どのようなことができるかを実際に試してみましょう。新しいプロジェクトで、つぎのようなコードを書いてIntentを発行するボタンを作成します。

var win = Ti.UI.currentWindow;

var button1 = Ti.UI.createButton({
    width: '100dp',
    heigth: '50dp',
    top: '30dp',
    left: '10dp',
    title: 'ACTION_SEND'
})

button1.addEventListener(
    'click',
    function(){
        var intent = Ti.Android.createIntent({
            action: Ti.Android.ACTION_SEND,
            type: 'text/plain',
            data:'hogehuga'
        });
        intent.addCategory(Ti.Android.CATEGORY_DEFAULT);
        Ti.Android.currentActivity.startActivity(intent);
    }
);
win.add(button1);

この方法でのIntentの発行では、Intentを受け取るほかのアプリを直接指定していないので、画面に受け取るアプリの選択肢がいくつか並びます。この例ではhogehugaというテキストをを表示できるアプリがすべて選択肢に挙がっているので、標準でインストールされているメーラーや、Twitterクライアントなどが選択肢に並んでいます。

画像

受け取ったデータの利用の仕方は受け取り手に任されているので、メール送信フォームに表示されるなどそれぞれのアプリで適宜利用されます。

このIntentが相手のアプリに届ける主なデータとなる部分がcreateIntentに渡っているオブジェクトのdataプロパティです。typeはこれを補助するものでMIMEタイプとほぼ同じように指定できます。そしてactionは与えられたデータをどう扱うかというもので、Ti.Androidオブジェクトのプロパティとしていくつか実装されているほか、文字列として自分で指定することもできます。たどえば、actionをTi.Android.ACTION_VIEW, typeを指定なし、dataをURLにしておくと、指定したURLをブラウザで開かせることもできます。この時、ブラウザがいくつかインストールされていれば、typeが 'text/plain' の時と同様に、開くブラウザを選択することもできます。

対象を絞ってIntentを発行する

もちろん、受け手を絞ってIntentを発行することもできます。たとえば、有名なバーコードリーダーであるzxingを起動してみましょう。zxingはAndroidマーケットで、⁠QRコードスキャナー⁠という名前で公開されていますので実機にインストールしてから試してください(zxingで検索すると最初に検索結果に現れます⁠⁠。

var button2 = Ti.UI.createButton({
    width: '100dp',
    heigth: '50dp',
    top: '90dp',
    left: '10dp',
    title: 'QR Reader'
})

button2.addEventListener(
    'click',
    function(){
        var intent = Ti.Android.createIntent({
            action: "com.google.zxing.client.android.SCAN",
        });
        intent.putExtra("SCAN_MODE", "QR_CODE");
        intent.putExtra("SCAN_MODE", "EAN_8");
        intent.putExtra("SCAN_MODE", "EAN_13");
        Ti.Android.currentActivity.startActivity(intent);
    }
);
win.add(button2);

このようなコードでバーコードリーダを起動することができます。actionをここでは文字列として指定しており、スキャンできるバーコードの種類をintent.putExtraで指定しています。外部のアプリに対してどのようなIntentを指定すればよいかはアプリ作者が公開していることが多く、zxingならhttp://code.google.com/p/zxing/wiki/ScanningViaIntentで、また筆者の所属する株式会社はてなのAndroidアプリであれば、Android向けAPIドキュメント一覧に情報がまとまっています。Javaのコードで解説されることが多いので、TitaniumのAPIリファレンスを参照しながらJavascriptのコードに読み替えて利用してください。

さて、バーコードリーダーアプリのような例では読み取ったデータ(バーコードの数値、文字列)を呼び出したアプリに返却して欲しいということもあり得ます。Intentはこのような情況にも対応しています。先ほどコードを次のように書き換えます。

button2.addEventListener(
    'click',
    function(){
        var intent = Ti.Android.createIntent({
            action: "com.google.zxing.client.android.SCAN"
        });
        intent.putExtra("SCAN_MODE", "QR_CODE");
        intent.putExtra("SCAN_MODE", "EAN_8");
        intent.putExtra("SCAN_MODE", "EAN_13");

        Ti.Android.currentActivity.startActivityForResult(
            intent,
            function(e){
                var intent = e.intent;
                var contents = intent.getStringExtra("SCAN_RESULT");
                
                alert(contents);
            }
        );
    }
);

このようにすると、バーコードを読み取ったあとに元のアプリに戻ってくることができます。コードに変更があるのは、startActivityメソッドがstartActivityForResultになり、第2引数に、callback関数が指定されている点だけです。この例では読み取ったバーコードの値をalertで表示しています。Intentで呼び出したアプリからの戻り値もIntentになっており、callback関数にわたってくるオブジェクトのintentプロパティから参照できます。返ってきたIntentにどのような情報が入っているかもアプリ次第なので呼び出すときと同様に、Intentを渡す相手のアプリのリファレンスを確認しておきましょう。

Intentを受け取る

ここまでIntentを発行する例を解説してきましたが、逆にほかのアプリからIntentを受け取ることもできます。ブラウザで選択している文字列を受け取って表示するようなアプリを実装してみます。

Javascirptのコードはこのようになります。

var receiveIntent = Ti.Android.currentActivity.getIntent();
if (receiveIntent) { 
  Ti.API.debug(Ti.Android.EXTRA_TEXT);
  alert(receiveIntent.getStringExtra(Ti.Android.EXTRA_TEXT));
}

このコードは、app.jsに書いておく必要があります。

Intentを受け取るにはコードの変更だけでなく、AndroidManifest.xmlの変更も必要です。このファイルはAndroidアプリの挙動を設定しているもので、通常は自動的に作られ、プロジェクトディレクトリのbuild/android/AndroidManifest.xmlに存在します。しかし、build以下のファイルはアプリをビルドする度に書き換えられてしまうので、build/android/AndroidManifest.xmlをコピーしてplatform/android/AndroidManifest.xmlというパスにファイルをつくります。platformディレクトリもその下のandroidディレクトリも存在しないので、自分でプロジェクトのディレクトリの中に作ります。コピーしたファイルの中に

<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.SEND" />
   <category android:name="android.intent.category.DEFAULT" />
   <data android:mimeType="text/plain" />
</intent-filter>

と記載します。このintent-filterというものが受け取れるintentを指定しています。このような設定にしておくと、ブラウザから文字列を選択し共有というコンテキストメニューを開くと作成中のアプリがリストにあるのが確認できると思います。

ブラウザから開いたメニューにアプリ名が見える
ブラウザから開いたメニューにアプリ名が見える

ブラウザから作ったアプリが開けるのが確認できたでしょうか。実際にアプリを選択すると、作成中のアプリが起動しalertで選択していた文字列を表示することができます。

iPhoneで同じことをするには?

iPhoneに全く同じ機能というのは存在しませんが、iPhoneアプリにはスキーマ連携という機能があります。これは、iPhoneのブラウザで、

hatenabookmark:/entry?url=http%3A%2F%2Fb.hatena.ne.jp%2Fguide%2Fiphone_app2

というような少し変わったurlを開くと、このURLのスキーマ部分(この例ではhatenabookmark)に関連付けられたアプリが起動するという機能です。このurlに含まれるpathやquery部分の情報はそのまま関連付けられたアプリ側に届けることができます。ブラウザで開くのと同等のことをする命令がTitaniumにも用意されており

Ti.Platform.openURL('hatenabookmark:/entry?url=http%3A%2F%2Fb.hatena.ne.jp%2Fguide%2Fiphone_app2')

と書くとブラウザからこのURLを開いたのと同じように、はてなブックマークのiPhoneアプリを起動することができます。また、このopenURLはAndroidでも利用でき、標準のブラウザで与えられたURLが開くようになっています。

まとめ

Androidらしい機能の一つとしてIntentを利用したほかのアプリとの連携について説明しました。今回は何ができるかを主に解説しましたが、Intentの連携については説明しきれていない部分がまだあります、ぜひgihyo.jpでの連載なども参照して理解を深めてみてください。AndroidのiPhoneとは違った魅力がみえてくると思います。

また、今回記事中で使ったコードはgithubに公開してありますので、あわせてご覧いただければと思います。

おすすめ記事

記事・ニュース一覧