技術解説
Javascript ライブラリの解説
技術解説、と言った所で、このプログラム自体はたいしたことやっていません。
見てもらえばわかりますが、ふつーに Javascript プログラム。
逆アセンブラみたいなもので、データを順に取ってきては、整形して表示しているだけです。
使い方も簡単。SocialLlama の URL を div タグで括って、ライブラリを呼び出すと、イベントが表示されます。
ソーシャルLlama URL の解析説明
ソーシャルLlama の URL を解析したい、と言う人のために情報。
(お、ちょっと技術解説らしくなった)
まず、ソーシャル Llama の URL は、 / で区切られています。
先頭は http://llama.location.profiles/ で始まり、次のブロックは、この URL 自体に付けられた名前です。最終的には無視されるようなので、気にする必要はありません。
次のブロックから、イベントのデータ。とはいえ、Llama の「Share event」で作られるデータでは、ブロックは1つだけです。手動でブロックを切り張りすると、複数のイベントを1つのデータとして送ることが出来ます。(普通のイベントは2つが対になっていますからね)
では、ブロック内のデータについて解説。
まず、ブロック内のデータは URL Encode されているので、デコードする必要があります。Javascript の decodeURI/decodeURIComponent 関数では、歴史的経緯もあって正しくデコードできないので注意しましょう。
デコードしたら、 | で区切ります。区切られた一つづつが、データとなります。
先頭はイベントの名前です。つぎは、イベントの設定。- で区切られた数字の列で示されますが、最後だけは「グループ名」です。詳細はプログラム中に書いてあるので読んでね。
3番目には、必ず : が入るようです。そして、4番目からがイベントのデータ。
さて、データは | で区切られています。なので、データ内部には | を入れることが出来ません。そのため、データには Llama 独自のエンコードが掛けられています。
データ内に \p があれば、それは | (pipe) がエンコードされたものです。
同様に、\d は - (dash) 、\b は \ (backslash) を意味します。
区切ったデータをすべて、デコード処理する必要があります。
これで、やっと「素の」データが得られました。これらのデータは、コマンドとパラメータに分かれます。基本的に、1つのコマンドの後ろに、複数のパラメータが付随します。
コマンド名は、1文字か2文字のアルファベット。2文字目は数字になることもあります。
コマンドには「状況」と「行動」がありますが、区別するようなフラグはありません。コマンド名から判別します。
多くのコマンドは、パラメータを1つだけとります。このパラメータは、0が無効、1が有効、と言うものが多いですが、2がトグルだったり、もっと多い選択肢が示されることもあります。これも、詳しくは僕のプログラムを読むと理解しやすいかと思います。
パラメータが連続値をとる場合、-1 に特別な意味合いが与えられることがあります。文字列だったり、ビットマップになっているパラメータもあります。
パラメータを複数とる場合もあります。個数を識別するフラグは無いので、コマンド名から判断しますが、幸い「可変個数」というようなコマンドはありません。
パラメータの個数や扱いは、本当にコマンドごとにまちまち。個別処理するしかありません。
一部のパラメータは、Base64Encode されたバイナリです。大抵は表示するだけなら無視できるものですが、インテントの送信だけは、内部を解析しなくては表示が行えません。これについては後述。
OR や AND 、待ちイベントなどは、その内部に「イベントデータ」を内包しています。
この場合、パラメータとして与えられたイベントはやはり、 | で区切られています。再帰処理してイベントを解析してください。
注記
NFCタグは、16進数16桁(8byte)の数値です。この数値を直接扱うのはわかりにくいため、Llama では「名前」をつけて管理できます。
Social Llama URL では、「NFCタグの検出」状況のパラメータにタグの数値だけが入れられており、名前は入っていません。そのため、名前を表示することは出来ません。(常に「不明」になります)
これは、このプログラムに限ったことではなく、Llama 自体に読み込ませた場合も同様です。
インテントの内部構造
インテントの送信、では、パラメータとして Base64Encode されたバイナリデータがついています。
この中身を解析しないことには表示を行えないのですが、中身は本当にバイナリデータなので、構造が良くわかりません。
以下に構造を「たぶん」で解説しますが、本当にあっている保障はありません。
また、以下の考え方に「パディング」と説明している部分があります。これは、無意味なデータが入っている、と言う意味ですが、本当は意味があるのに気づいていないだけ、と言う可能性は高いです。
基礎概念
Android のプログラムは、基本的には Java です。JavaVM の亜種(Jakarta)の上で動きます。
なので、バイナリデータの中も、Java で扱いやすい形式です。
数値はすべて 32bit です。格納されるときは 32bit アライメントされています。
文字列は UTF-16 です。終端文字は U+0000 です。数値格納を 32bit アライメントするため、奇数文字列のデータの場合、最後に 16bit のパディング U+0000 が付加されます。
複数のデータをバイナリに格納するため、文字列の先頭には数値で文字列長が付与されています。この文字列長には終端文字は含みません。つまり、LASCIIZ 文字列になっています。
Intent のデータとしては、パッケージ、クラス、行動、カテゴリ、データ、データタイプがあります。
このうち、データとデータタイプはどちらか片方しか意味を持たない、排他構造になっています。
また、クラスはパッケージの下位の概念になります。
バイナリ内部は、これらを考慮した構造になっているようです。
文字列長が 0 のときは、文字列の先頭が終端文字 U+0000 のデータになります。この場合、32bit アライメントのため、もう一度 U+0000 が繰り返されます。
文字列長が -1 (0xffffffff) のときは、文字列データ自体が存在しません。すぐに次のデータとなります。