URIスキーマを試してみました。

1,050 views
Skip to first unread message

吉岡 梅

unread,
Jul 20, 2010, 1:19:49 AM7/20/10
to AIR/Flash for Android
吉岡です。
URIスキーマを試してみました。

URIスキーマというのは、自分で作成したアプリに対して、固有のURIを指定できる仕組みです。
固有のURIを指定することによって、ブラウザ等からそのURIを使ってアプリを起動する事が
できるようになります。

この固有のURIは、Androidアプリの設定ファイル「AndroidManifest.xml」内で指定します。
…のですが、AIR for AndroidではAndroidManifest.xmlは自動作成されますので、例によって
AIRアプリの設定ファイル内にて、<android>タグを使って書き込みの依頼をしておきます。

具体的には、「appName-app.xml」内に、次のような要素を追加しておきます。

<android>
<manifestAdditions>
<launcherActivity>
<data>
<![CDATA[
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="ここにURIスキーマ"/>
</intent-filter>
]]>
</data>
</launcherActivity>
</manifestAdditions>
</android>

<data android:scheme="ここにURIスキーマ"/>の箇所に、自分のアプリを呼び出す際に
使用したい名前を指定するわけですね。

とりあえず「testApp」という名前で登録をしたい場合には、

<data android:scheme="testApp"/>

でOKです。
(このURIスキーマの命名規則はちょっと調べていないのですが、反転ドメイン形式のような
おきまりのルールみたいなのはあるんでしょうか?jpCirueloTestAppのが無難、みたいな。)

この設定を行ったアプリは、ブラウザ上のハイパーリンクテキストから、
URIスキーマを利用して起動できます。
つまりは、

<a href="testApp://">「testApp」として登録したアプリを起動</a>

と、aタグを記述しておき、これをブラウザ上で表示してクリックすればアプリが起動します。


■パラメータを渡す

アプリを起動する際に、何らかの情報をパラメータとして渡したい場合には、
HTTPでのGETのように、URIエンコードしたパラメータを付加する事もできます。
具体的には、

<a href="testApp://arg1=value">「testApp」として登録したアプリを起動</a>

のように記載するわけですね。


■AIRアプリ側で起動されたことを検知するには

さて、この仕組みを使ってブラウザからAIRアプリを起動した場合、アプリ側では
NativeApplicationのinvokeイベントが発生し、invokeイベントのイベントオブジェクトの
argumentsプロパティに、その内容が渡されます。

こんな感じで受ける準備をしておくわけですね。

//NativeApplicationのinvokeイベントで起動時の情報を受ける
var na:NativeApplication = NativeApplication.nativeApplication;
na.addEventListener(InvokeEvent.INVOKE,func)

function func(e:InvokeEvent):void{
msg.text = "起動イベントを受け取りました\r"
//argumentsの長さで起動オプションがあるかどうか(URIスキーマで呼び出されたかどうか)を判定
if(e.arguments.length>0){
msg.appendText("受け取ったパラメータは、" + e.arguments[0].toString())
}else{
msg.appendText("通常起動しました。")
}
}

この時、invokeイベントのイベントオブジェクト内のarguments[0]には、起動時に渡された
文字列が格納されています。単に、

<a href="testApp://">「testApp」として登録したアプリを起動</a>

として起動した場合にも、「testApp://」という文字列が格納されています。

<a href="testApp://arg1=value">「testApp」として登録したアプリを起動</a>

のようなパラメータがある場合は、まるごと「testApp://arg1=value」という文字列が格納されています。
パラメータのパースは自分でやってください、って事なんでしょね。

ともあれ、NativeApplicationのinvokeイベントを使用すれば、URIスキーマによって起動されたかどうかや、
起動時に渡されたパラメータを受け取ることも可能です。


■AIRアプリから直接URIスキーマを利用して他のAIRアプリを起動するには -失敗例

さて、URIスキーマの仕組みを使って、AIRアプリからAIRアプリを起動する事はできるのでしょうか。
ちょっと試した限りは「条件付きでできるけど、ちょっとスマートじゃないぜ」という感じでした。

まずは単純に、navigateToURLで行ってみました。

var req:URLRequest = new URLRequest("testApp://");
flash.net.navigateToURL(req);

これは、セキュリティエラーが送信側のAIRアプリ内で発生し、メッセージを送ることもできずに
コケてしまいました。残念。


■AIRアプリから直接URIスキーマを利用して他のAIRアプリを起動するには -迂回例

どうも普通にリクエストを送ると、セキュリティエラーではじかれてしまうようです。
そこで、StageWebViewを使って、アプリ上にブラウザコンテナを表示し、StageWebView内の
aタグからURIスキーマを設定したアプリを呼び出してみました。

StageWebViewクラスは、AIRアプリ内にブラウザのコンテナを表示する事ができるクラスです。
また、loadStringメソッドを利用すると、任意のHTML表現を持った文字列を、webコンテンツと
して表示してくれます。この仕組みを利用するわけですね。

//簡易ブラウザを表示
var wv:StageWebView = new StageWebView();
var rect:Rectangle = new Rectangle(0,0,480,300);
wv.viewPort = rect;
wv.stage = stage;

//HTMLテキストを流し込み
var xml:XML =
<html>
<body>
<a href = "testApp://"}>URIスキーマを利用して起動</a>
</body>
</html>

wv.loadString(xml.toXMLString());

※設定ファイルに、
 <uses-permission android:name="android.permission.INTERNET"/>
 の設定が必要です

StageWebViewは、ASではかなり特殊なクラスです。画面に表示する系のクラスなのですが、
表示リストには連なれません。つまりはaddChildやremoveChildで扱えないわけですね。
StageWebViewを表示するには、stageプロパティに、Stageへの参照をセットします。
すると、アプリの最上位に表示されるようになります。

また、とりあえずは「表示専門」といったような用途であり、ASとの細かな連携はできません。
(URIスキーマを使って自分自身にパラメータを渡すことはできますが、冗長ですよね)

しかし、前述したようにloadStringメソッドを使用すれば、表示する内容をゼロから
コントロールする事はできますので、とりあえずURIスキーマ発射台としては使用できます。

あまりスマートとは言えませんが、とりあえずはAIRアプリから他のAIRアプリの起動ができるようになりますね。


■バイナリデータの受け渡しはできるのか

文字列データの受け渡しができる事はわかりましたが、バイナリデータはどうでしょうか?
ちょいと試してみました。URIを使用するので直接バイナリで、というわけにはいかないので、
mxパッケージに用意されているmx.utils.Base64Encoderを利用して、base64エンコードをしてから
渡す作戦で試してみました。

例によって適当なBitmapdataを作成し、それをエンコードして渡しています。

//base64エンコードしたパラメータ付きのURIを作成するヘルパ関数
function createURI():String{
//Bitmapdata → ByteArray(PNGデータ) → String(base64エンコード)
var bmd:BitmapData = new BitmapData(200,200,false,0xFFCC00);
var data:ByteArray = new PNGEncoder().encode(bmd);
var enc:Base64Encoder = new Base64Encoder();
enc.encodeBytes(data);
//得られた値をURIスキーマに付け加える
var s:String = "'jpCirueloGetter://arg1=" + getEncodedBMPData(bmd) +
"'";
return s;
}

//base64エンコードした文字列をパラメータとして持つURIスキーマをaタグに埋め込んで表示
var wv:StageWebView = new StageWebView();
var rect:Rectangle = new Rectangle(0,0,480,300);
wv.viewPort = rect;
wv.stage = stage;

var xml:XML =
<html>
<body>
<a href = {createURI()}>URIスキーマを利用して起動</a>
</body>
</html>
wv.loadString(xml.toXMLString());


こんな感じですね。
あとは、受け取る側のinvokeイベントに割り当てた関数以内で、この値をパースして
デコードする仕組みを作ってあげればOKです。
デコードする場合には、mx.utils.Base64Decoderを使用します。

ちょっと雑ですが、こんな感じで

function onInvoke(e:InvokeEvent){
//起動時に渡されたパラメータから、必要な部分だけを切り出す
var uri:String = "testApp://arg1="
var s:String = e.arguments[0].toString().substr(uri.length);
//base64でコード
var dec:Base64Decoder = new Base64Decoder();
dec.decode(s);
var ba:ByteArray = dec.toByteArray();
//得られたバイナリデータ(今回はPNGファイル)を画面に表示
var loader:Loader = new Loader();
addChild(loader)
loader.loadBytes(ba);
}

と、こんな感じでbase64エンコード/デコードを経由すれば、バイナリデータの受け渡しも
可能でした。
ただ、あまり大きなデータは、URIスキーマのパラメータが長すぎるのか、コケてしまう事も
ありました。画像データで言うと、形式にもよりますけど、画面全体のスクリーンショットを
送ろうとしたら、コケました。

これは、エラーログを見る限り、AIR for Android的な限界というよりも、Android的な限界
なのかなあ、という感じです。
Javaで作成したアプリからAIRアプリへとURIスキーマ経由で大きなデータを渡そうとした場合
にも、おそらくコケるんじゃないかな?と思います。

ちょっとしたテキストデータや、それほど大きくないバイナリデータの受け渡しは、
かなりスムースにいけますよ。

■まとめ

URIスキーマを使えば、ブラウザ経由でアプリ間のちょっとした連携ができそうです。
AIRアプリ同士だけでなく、Javaで作成したAndroidアプリとデータをやり取りしたい場合にも
利用できそうなので、複数の小さなアプリを用途に応じて組み合わせて使用したい場合等に
便利そうですね。


ではでは。

---
シルエロ:吉岡梅
umeyo...@gmail.com

竹林真

unread,
Dec 9, 2010, 9:45:40 AM12/9/10
to af...@googlegroups.com
吉岡様

竹林です、URIスキーマのご確認ありがとうございます。

Invokeについて試してみたらイベントリスナーをどこに設置しても実行することができました。
一点つまづいた点があって、Androidにデフォルトで搭載しているブラウザで試した場合、
インテントフィルタにscheme="http" の設定を行うとイベントを拾うことができませんでした。
ここがtestappなどの場合は正常に起動されました。
ただし、DolphinBrowserなどの他のブラウザではhttpを指定した場合のイベントも拾うことができました。

Googleグループへの投稿ができていなかったようなので、今後はGoogleグループにてやり取りを行います。

2010年12月8日18:19 吉岡梅 <umeyo...@gmail.com>:
> 吉岡です。
>
> ちょっと試してみましたが、firstViewのviewActivateイベント処理内に記述してもOKでしたよ。
> 確かInvokeイベントは待ち行列のような仕組みになっていたはずですので、極端なことを言えば、任意のボタンを押した際の処理でaddEventListenerしても、起動時の情報が得られるかと思います。
>
> 起動時に「どうやって起動されたのか」の情報は記録されているので、あとはどのタイミングでそれを「取り出すか」というような感じでしょうか。
>
> ですので、アプリケーションが起動していない状態でも大丈夫と思いますよ。
>
> ただ、私自身は普段はあまりFlashBuilderを使わないで、ついついFlashでコードを書いてしまう性質ですので、間違っている点があるかもしれません。
> 「そうじゃないですよ」という点があれば、識者の方、ご指摘をお願いします。
>
> ではでは。
>
> 2010年12月8日0:18 BeMarble <mkt...@gmail.com>:
>> 竹林と申します。
>> AIR/Flash for Androidグループの活性化を期待しています。
>>
>> URIスキーマを使用する際の実装について一点ご質問です。
>>
>> サンプルにありました下記コードにつきまして、MXMLを使用して開発を行う場合
>> InvokeEventを待ち受ける場合はどのフェイズでaddEventListenerを行うのが適切なのでしょうか?


>>
>> //NativeApplicationのinvokeイベントで起動時の情報を受ける
>> var na:NativeApplication = NativeApplication.nativeApplication;
>> na.addEventListener(InvokeEvent.INVOKE,func)
>>
>>

>> もしapplicationCompleteイベント発生時にInvokeEventをリッスンするコードにすると、
>> イベント受け取り側アプリケーションを起動していない場合はブラウザからのイベントを
>> 待ち受けていない状態になるのでしょうか。
>>
>> 以上よろしくお願いいたします。

>>> umeyoshi...@gmail.com
>
>
>
> --
>
> シルエロ:吉岡 梅
> umeyo...@gmail.com
> yosh...@ciruelo.jp
> 開発環境:FlashCS5、Flash Builder Burrito
> Android実行環境:Nexus One, Froyo2.2, Adobe AIR 2.5.1.1774
>

ゴマ

unread,
Aug 29, 2012, 7:24:26 AM8/29/12
to AF...@googlegroups.com
初めて投稿します。

元記事にあります"AIRアプリから直接URLスキーマを利用して他のAIRアプリを起動"と
外部にあるHTMLのリンクからアプリを起動する方法を試しているのですが、
どうもうまくいかず悩んでおります。

標準ブラウザからは下記のHTMLから普通に立ち上がるのですが、自作のアプリからは
なぜか起動せず"ページが見つかりません"と表示されてしまいます。

■FLASH内のソース
var swv1:StageWebView = new StageWebView();
swv1.stage = stage;
swv1.viewPort = new Rectangle(0,0,720,404);
swv1.loadURL("http://○○○/sample.html");

var swv2:StageWebView = new StageWebView();
swv2.stage = stage;
swv2.viewPort = new Rectangle(0,404,720,876);
var html_text2:String = "<a href='umaigame://com.gignosystem'}>URLスキーム</a>";
swv2.loadString(html_text2);


■HTML内のソース
<a href="umaigame://com.gignosystem">URLスキーム</a>
※うまい棒アプリのURLスキームです。

ApplicationManifest.xml
・・・

<uses-permission android:name="android.permission.INTERNET"/>
・・・

■開発環境
adobe cs5.5
galaxy s
xperia gx
中華Pad

原因をご存知でしたらご教授頂ければと思います。


2010年7月20日火曜日 14時19分49秒 UTC+9 吉岡 梅:

吉岡梅

unread,
Aug 29, 2012, 9:20:15 AM8/29/12
to af...@googlegroups.com
ゴマさんはじめまして。元記事を投稿させていただきました、吉岡です。

実は、このStageWebView経由でURIスキーマを利用する方法は、現在は使用できません。
いつのタイミングだったかちょっと失念してしまいましたが、結構前に使用できなくなりました。

では、現在はどうすれば良いのかと言いますと、

いわゆる「ネイティブ拡張(ANE連携)」機能を利用します。
Androindのアプリケーション間の連携(インテントの利用)に関しては、「ANE Android インテント」等のキーワードで検索をしてみて下さい。
おそらく、いろいろな情報や、インテントを利用できるライブラリ・サンプルコードなどが見つかると思います。

ではでは、失礼します。

---
よしおか




2012年8月29日 20:24 ゴマ <golgo...@gmail.com>:
> --
> /**
> *
> * AIR/Flash for Android
> * http://groups.google.co.jp/group/AF4A
> *
> * To post to this group, send email to
> * AF...@googlegroups.com
> *
> * To unsubscribe from this group, send email to
> * AF4A+uns...@googlegroups.com
> *
> */

大森厚志

unread,
Aug 29, 2012, 10:31:18 AM8/29/12
to af...@googlegroups.com
吉岡さん
ご返信ありがとうございます!

使用できなくなってたんですね・・・。

早速拡張機能で試してみようと思います。

助かりました!!ありがとうございます!!



2012年8月29日 22:20 吉岡梅 <umeyo...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages