2013年6月28日金曜日
あるき音システムをわかりやすく
あるき音システムが理解できないという指摘を受け、説明用の図を作成しました。
(ケイさんごめんなさい)。
あるき音のイメージはこうです。
屋内施設の中(たくさんの場所)にスピーカー+CDプレーヤーを設置し、異なるIDのあるき音を鳴らしておきます。
スマホを手にした顧客がこの施設を歩くと、クラウド(サーバー)は次のようなデータを収集できます。
[2013/08/21 12:13:30][スマホ123号][AREA9]
:
[2013/08/21 12:13:40][スマホ123号][AREA8]
:
[2013/08/21 12:15:20][スマホ123号][AREA6]
:
[2013/08/21 12:21:50][スマホ123号][AREA2]
:
[2013/08/21 12:25:03][スマホ123号][AREA1]
あとでこのデータを解析すると、この顧客の移動パターンが把握できるというものです。
これらたくさんの行動パターン解析結果は、施設構成レイアウトや顧客誘導経路等の営業戦略の基礎データに利用可能です。
※ スマホを手に持って歩くと「いいことがある」「楽しい」という仕掛けが必要です。
→ 自動ポイント配布、シークレット割引メッセージ表示などのスマホアプリを開発し、バックグララウンドであるき音アプリを動かしておく。
※ スマホのマイク性能(指向性)、スマホの持ち方(マイクを指でふさいでない)、歩く速さなどで、あるき音を聞き取りできない場合が多々発生します。
→ このため完璧な人間の動線をトレースすることは困難です。
あるき音アプリのダウンロードはこちらから
2013年6月22日土曜日
あるき音システム
かくれ音システム応用版として、「あるき音」をリリースしました。
あらかじめ屋内施設(ショッピングモールやデパート)のあちこちから聞こえない音「あるき音」を鳴らしておきます。
スマホはあるき音を聞き取ると、その音に含まれている情報をサーバーに送ります。
この仕組みにより顧客の移動経路、行動パターンを把握することができるため、販売戦略に役立てることが可能になります。
区画ごとにスピーカーを設置し、異なるあるき音を鳴らしておくことで、聞き取りエリア内を通過したスマホを把握します。
※ かくれ音とあるき音の違い
かくれ音IDは約1.2秒ごとに繰り返し鳴らしていますが、あるき音IDはデータ量を減らし約0.6秒ごとにしています。歩きながらのエリア通過を想定しているため、短いデータ長を設定しました。
あるき音アプリのダウンロードはこちらから
2013年6月18日火曜日
かくれ音システム 実測結果
かくれ音システムは屋外でどれくらいまで音が届くのかを実測してみた。
まずは再生環境(スマホ+スピーカーを地べたにそのままってどうよと思いつつ ・・ )
ちなみにボリューム設定は約40%の位置に
これ以上ボリュームを上げると、音がひずんで「ういーん」という音が聞こえてくるんです。
では実際にスマホを片手にテストしてみました。
まずはPanasonic P-01D
距離が離れると、スマホのマイクをスピーカーに向けないと厳しいです。
(だってヤフオクで新品未使用が5000円という値段に釣られたスマホですし ・・ )
でもこんな感じの場所で3秒ほど待機すると、見事受信できました!
引き続きNEC MediasTab N-08D
Panasonicは超えるかなと思ってましたが、これまさに余裕!
結局この位置でスマホのマイクをスピーカーに向けると3秒ほどで受信できました。
実際の位置関係をGoogleMAPより調べるとこうなりました。
以下の写真はGoogle Mapとストリートビューから抜粋した位置関係です。
Panasonic P-01Dでも20m以上! MediasTabだと40m以上です。
Androidスマホのマイク性能やマイク指向性などによって到達距離は異なることは当然ですが、この結果には自分でも驚きです。
※ ただしスマホのマイク性能や周りの状況によって伝達距離が大きく異なると予想されるため、あくまでも伝達距離は10m程度という仕様にしておきます。
ちなみにこの間にペットの犬が3匹いますが、まったく吠えることありませんでした。
犬に「聞こえた?」って聞いても無視されてしまいました。
かくれ音アプリのダウンロードはこちらから
2013年6月17日月曜日
かくれ音システム
ひさしぶりのブログ更新。
ずっと音を使ってのデータ伝送「かくれ音(かくれおん)」システムの開発を行っていました。
テーマはまさにシンプル「音で伝える」です。
人間には聞こえない音域(18K~20KHz)の音を出し、スマホのマイクで聞き取ります。
スマホ毎に異なるマイクの指向性などをどう克服するか、本当に苦労しました。
現在Google Playに正式リリースする前段階で、最終テストを行っています。
iPhone版はまだ追いついていません(残念)。
こんな使い方を考えています。
聞こえない音を再生するスピーカーはONKYO社製、GX-70HDを推奨機種としています。
大きさ、再生周波数、出力パワー、そして値段でベストな機種と判断しました。
http://www.jp.onkyo.com/pcaudio/poweredspeaker/gx70hd/index.htm
(現在Amazonで1万円前後です)
興味がある方はお気軽に連絡ください。
基本的な販売対象は「聞こえない音データ(wavファイル)」と「サーバー使用費」です。
Androidアプリは無料で公開しますが、有料でカスタマイズアプリ開発なども対応します。
ずっと音を使ってのデータ伝送「かくれ音(かくれおん)」システムの開発を行っていました。
テーマはまさにシンプル「音で伝える」です。
人間には聞こえない音域(18K~20KHz)の音を出し、スマホのマイクで聞き取ります。
スマホ毎に異なるマイクの指向性などをどう克服するか、本当に苦労しました。
現在Google Playに正式リリースする前段階で、最終テストを行っています。
iPhone版はまだ追いついていません(残念)。
こんな使い方を考えています。
聞こえない音を再生するスピーカーはONKYO社製、GX-70HDを推奨機種としています。
大きさ、再生周波数、出力パワー、そして値段でベストな機種と判断しました。
http://www.jp.onkyo.com/pcaudio/poweredspeaker/gx70hd/index.htm
(現在Amazonで1万円前後です)
興味がある方はお気軽に連絡ください。
実機デモ、打ち合わせなど対応可能です。
基本的な販売対象は「聞こえない音データ(wavファイル)」と「サーバー使用費」です。
Androidアプリは無料で公開しますが、有料でカスタマイズアプリ開発なども対応します。
2013年4月10日水曜日
Webカメラ画像のリアルタイム表示
Webカメラの映像をAndroidスマホで表示するデモを何度か受けたことがある。
その際いつも指摘されることが、スマホ側での画像の遅延。
動作環境は以下のようなイメージ。
USBカメラの画像は数秒遅れでAndroid端末に表示される。
ストリーミングソフト=WebCamXPでは3~5秒、YawCamで2秒程度。
USBカメラとAndroid端末が離れている場合は問題ないんですが、デモなどでは絶対指摘されてしまいます。
「この遅れはなんとかならないのか ・・ 」と。
確かにそうなんですよね。
車のバックモニタなどを想定した場合、2~3秒遅延があれば「ゴツン!」間違いなしです。
ストリーミングソフトの自作を想定して、どこまでリアルタイムに近づけるか調べてみた。
USBカメラをDirectShowなどで取り込む場合、取り込みに必要な時間は33mS。
1/30秒での画像取り込みですね。
取り込んだ画像サイズは9216154バイト(640*480*3+α:ヘッダ分)でした。
この画像(Bitmap)をメモリ上でjpegに変換した場合(品質40%)
処理時間に約31mS
出力画像サイズは25871バイト(原本の約1/35)でした。
※ ファイル出力していません。あくまでもメモリ上だけの展開です。
あとはWifiでの転送速度とAndroidの受信~表示の遅れ。
これはJNI(C++)などを使ってがんばるしかないです。
実際には1秒に10枚程度の画像でパラパラ漫画的に、遅延は100mS程度って感じでしょうか。
(これでも2メガBPSの通信速度が必要で、3G回線だととっても無理)。
これで実用レベルに達するなら、DirectShowでの画像取り込み~Jpeg変換~Androidへの転送ってのが実現できそうです。
MotionJPEGでのパラパラ漫画ストリーミングです。
最近はやりのストリーミングもリアルタイムには厳しいので ・・
2013年4月8日月曜日
Webカメラの画像表示(Panasonicカメラ)
1年ほど前に調査していたネタ。
PanasonicのWebカメラをAndroidで表示したい。
たとえば ・・
株式会社リネット様
http://180.131.124.38:8101/CgiStart?page=Single&Language=1
株式会社SimPro様
http://simpro.mydns.jp:84/CgiStart?page=Single&Resolution=640x480&Quality=Standard&Mode=JPEG&RPeriod=65535&Size=STD&PresetOperation=Move&SendMethod=1&Language=1
PCのブラウザでは動画を表示できますが、Androidのブラウザでは表示できません。
そしてまたAndroid版FireFoxだけは表示できるのも謎です。
ではこれらの映像をAndroidのアプリで表示するにはどうしたらいいでしょうか?
※ HTMLコードばかりで長くなってしまいますが、ご容赦ください。
追いかけていく ポイントはこれらの中のほんの少しだけなので。
■ 上記ページのHTMLコードを見てみよう。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN"> <HTML> <HEAD> <META HTTP-EQUIV="expires" CONTENT="0"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> <META NAME="ROBOTS" CONTENT="NONE"> <META NAME="ROBOTS" CONTENT="NOINDEX,NOFOLLOW"> <META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS"> <TITLE>Network Camera</TITLE> </HEAD> <FRAMESET border=0 frameSpacing=0 rows=30,8,* frameBorder=0> <FRAME name=bar src="CgiTagMenu?page=Single&Language=1" scrolling=no NORESIZE> <FRAME name=hrbar src="BarFoot.html" scrolling=no NORESIZE> <FRAME name=body src="ViewerFrame?page=Single&Language=1"> </FRAMESET> </HTML>
これだけ? トップページには確かにこれだけ ・・ 3つのフレームがあるだけです。
■ それではこの内部を追いかけてみる。
映像が含まれていると思われる場所のソース
ViewerFrame?page=Single&Language=1をクリックして出てきたソースを見てみる。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN"> <HTML> <HEAD> <META HTTP-EQUIV="expires" CONTENT="0"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> <META NAME="ROBOTS" CONTENT="NONE"> <META NAME="ROBOTS" CONTENT="NOINDEX,NOFOLLOW"> <META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS"> <TITLE>ViewerFrame</TITLE> <SCRIPT Language="JavaScript"> <!-- if(top.location.href.match("/CgiStart") == null) { top.location.href = "CgiStart?page=Single&page=Single&Language=1"; } // --> </SCRIPT> </HEAD> <FRAMESET COLS="123,*" FRAMEBORDER=0 BORDER=0 FRAMESPACING=0> <FRAMESET ROWS="26,*"> <FRAME SCROLLING=no SRC="nphControlCamera?Direction=&Resolution=640x480&Quality=Standard&Size=STD&Width=640&Height=480&NewPosition.x=&NewPosition.y=&PresetOperation=Move&Language=1&RPeriod=0" NAME="Message"> <FRAME SRC="nphPanTiltControl?Resolution=640x480&Quality=Standard&Size=STD&PresetOperation=Move&Language=1&RPeriod=0" NAME="Control"> </FRAMESET> <FRAMESET ROWS="24,*"> <FRAME SRC="CgiTitle?Resolution=640x480&Size=STD&Sound=Enable&Language=1" NAME="audio" NORESIZE SCROLLING="NO"> <FRAME SRC="ImageViewer?Resolution=640x480&Quality=Standard&Size=STD&PresetOperation=Move&Data=0&Frame2=PanTilt&Type=&Language=1&RPeriod=0&Sound=Enable" NAME="right"> </FRAMESET> <NOFRAMES> <BODY> </BODY> </NOFRAMES> </FRAMESET> </HTML>
映像データと思われるものはまだない。
でもAndroid版FireFoxでは表示されるので、これらのコードをたどっていくと映像データが存在するはず!
■ もう少し追いかけてみよう。
上記コードの中から、この部分をクリックして出てきたソースを見る。
ImageViewer?Resolution=640x480&Quality=Standard&Size=STD&PresetOperation=Move&Data=0&Frame2=PanTilt&Type=&Language=1&RPeriod=0&Sound=Enable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN"> <HTML> <HEAD> <META HTTP-EQUIV="expires" CONTENT="0"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> <META NAME="ROBOTS" CONTENT="NONE"> <META NAME="ROBOTS" CONTENT="NOINDEX,NOFOLLOW"> <META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS"> <TITLE>ImageViewer</TITLE> <META HTTP-EQUIV="Refresh" CONTENT="1800;URL=ImageViewer?Resolution=640x480&Quality=Standard&RPeriod=3&Size=STD&Sound=Enable&Language=1"> <META http-equiv="Content-Script-Type" content="text/javascript"> <META http-equiv="Content-Style-Type" content="text/css"> </HEAD> <BODY BGCOLOR="#EFEFEF" TEXT="#ffffff" LINK="#ffffff" VLINK="#ffffff" ALINK="#ffffff" TOPMARGIN="0" LEFTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0"> <!-- ** view ** --> <FORM METHOD="POST" ACTION="nphControlCamera" TARGET="Message"> <INPUT TYPE=hidden NAME="Width" VALUE="640"> <INPUT TYPE=hidden NAME="Height" VALUE="480"> <INPUT TYPE=hidden NAME="Language" VALUE="1"> <INPUT TYPE=hidden NAME="Direction" VALUE="Direct"> <INPUT TYPE=hidden NAME="PermitNo" VALUE="-2104609529"> <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0> <TR><TD title="マウスでクリックした位置を画面の中央に移動します。"><INPUT TYPE=image NAME="NewPosition" SRC="nphMotionJpeg?Resolution=640x480&Quality=Standard" WIDTH=640 HEIGHT=480 BORDER=0></TD></TR> </TABLE> </FORM> <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" style="padding-left: 10px;"> <TR><TD HEIGHT=1></TD></TR> <TR><TD HEIGHT="24"><FONT Face="Arial" Style="font-size: 11px;" COLOR="blue">音声が聴こえないときはこちらをクリックしてください</FONT></TD></TR> <TR><TD><A HREF="http://panasonic.biz/netsys/netwkcam/support/technic/sound/index.html" target="_blank"><FONT Face="Arial" Style="font-size: 11px;" COLOR="blue">http://panasonic.biz/netsys/netwkcam/support/technic/sound/index.html</FONT></A></TD></TR> <TR> <TD HEIGHT="24"> <FONT FACE="Arial" STYLE="font-size: 11px" COLOR="black"> <B>IPv4 で動作中</B> </FONT> </TD> </TR> </TABLE> <!-- ** /view ** --> </BODY> </HTML>
!!!! SRC="nphMotionJpeg? ・・・" というのが気になりますね!!!
ここをクリックしてみましょう。
■ こういう表示になります。
--myboundary Content-length: 31015 Content-type: image/jpeg リ�#タ� ン � ��������������������ロ�C� ( (H0 0H`H&(6M`phX::JhpplhXhjpppjoppzzzzzロ�C 0 2dB8Dddddddddddddddddddddddddddddddddddddddddddddddddddタ� � "� ト� �� �������� ト�オ � �� } � !1A Qa "q 2¢。 #Bアチ Rム�$3br�
: 以下、文字化けした記号が続く。
やっとたどり着きました!
文字化けした記号部分を31015バイト分受信して、そのデータをjpeg表示したらカメラ画像が出てきます。
■ Androidアプリで実現するには、こういう手順です。
PanasonicカメラのHTMLコードから上記のコードを追いかけ、SRC="npnMotionJpeg" というキーワードまでたどっていく。
Content-lengthで取得できるバイト数分のメモリ領域を確保し、その内部に受信データを蓄積する。
蓄積したデータをjpeg画像表示~メモリ解放を行う。
もう一度ここにアクセスすると、バイト数、データ内容が変化しているため、メモリ確保、jpegデータ取得、jpegデータ表示、メモリ解放を繰り返す。
この方法でPanasonicカメラの動画表示ができます!
ここまで追いかけて表示してくれるAndroid用ブラウザはFireFoxだけだったんですね。
やり方がわかれば実現はさほど難しくありません。
是非興味がある方、お試しください。
現段階では都合上ソースの公開は控えておきますが、興味のある方は連絡ください。
2013年4月5日金曜日
Windowsでのリアルタイム処理(2)
昨日に引き続き、Windowsでのリアルタイム処理をテストしてみた。
今回のテスト環境は
CPU Core-i3-2330M
メモリ 4ギガ
Windows7 Ultimate 64bit版 ServicePack1
開発環境 VisualStudio 2008
ソースは変更せず、こちらの環境で再ビルドを行い実行してみた。
下図はバックグラウンドでファイルコピーを行いながら、500マイクロ秒周期での呼び出しができているかを確認している状態を示している。
ほぼ500マイクロ秒で動いているが、途中1600マイクロ秒(1.6ミリ秒)、793マイクロ秒などがちらほら出現している。
※ ディスクコピーを行っていない状態では、500マイクロ秒近辺で安定している。
昨日の結果から、単純にハードウェア(CPU)のパフォーマンスによる差だけではなさそう。
CPU使用率が100%に達していないため、強制的にタスク切り替えなどが発生し、そのための遅延のような気がする。
WindowsのOS内部まで入り込んで、リアルタイム制御を実行するというものもあるが、そこまでシステムに入り込まなくても、ある程度リアルタイムを実行できる方法はないものだろうか ・・・
もう少し調査してみよう。
2013年4月4日木曜日
Windowsでのリアルタイム処理
RTL(Real Time Linux)のようなリアルタイム処理がWindowsでできるのだろうか?
テストプログラムを作って確認してみた。
実行マシン
CPU = Core-i7 870 2.93GHz
メモリ = 4G
Windows8 Pro with Media center 32bit版
開発環境 VC++/Express2008
約500マイクロ秒周期でクロック値をバッファリングできていることが表示された。
単純にみると、RT-Linuxと同等のことができている。
ただし背後に隠れているからくりは存在しているのだが。
途中ディスクアクセスなどが発生したらどうなるのだろう ・・・
お客さんからはいつもミリ秒単位できちんと関数を呼び出してなどと言われるが、そのたびにWindowsではOSが保障してないから難しいんですよと回答していた。
システム構成、ハードウェア構成を考えたら、こいつは利用できるかもと思う。
もうしばらく落とし穴などを調べてから、提案してみよう。
というわけでソースの公開はもう少し熟考してから(する? しない? 現状不明)。
興味がある方は声をかけてください。
2013年4月1日月曜日
AIDL呼び出しの処理時間
Androidアプリ間連携などで使用できるAIDLの処理時間を調べてみた。
テストに使用したタブレットはNEC N-08D
http://www1.medias.net/jp/sp/n08d/
テストの動作イメージを下図に記載する。
処理1) AIDL経由でバッファ転送処理を100000回繰り返し呼び出す。
処理2) AIDL経由でバッファ転送処理を1度のみ呼び出し、内部で10000回繰り返す。
計測した処理時間は以下のようになった。
処理1 処理2 AIDL実質呼び出し時間
1回目 34.702秒 0.154秒 0.34548ミリ秒
2回目 34.028秒 0.151秒 0.33877ミリ秒
3回目 34.034秒 0.176秒 0.33858ミリ秒
4回目 33.914秒 0.147秒 0.33767ミリ秒
5回目 33.882秒 0.176秒 0.33706ミリ秒
6回目 33.596秒 0.152秒 0.33444ミリ秒
7回目 33.503秒 0.149秒 0.33354ミリ秒
8回目 34.122秒 0.148秒 0.33974ミリ秒
9回目 33.842秒 0.146秒 0.33696ミリ秒
10回目 33.737秒 0.149秒 0.33588ミリ秒
※ AIDL実質呼び出し時間は(処理1時間-処理2時間)/100000で算出した。
この結果から、AIDL経由での呼び出しには約0.33ミリ秒の時間が必要なことがわかる。
一度関数呼び出すだけで0.3ミリ秒かかるということは、Javaだからということを考慮してもかなり遅い。
そこでもう少し考えてみた。
バッファ転送処理はJNI(C++)で128バイトのデータ転送を行っている。
転送のためにGetByteArrayElementsとReleaseByteArrayElementsを呼び出しているため、AIDL呼び出しではなく、実はこの関数ここで時間がかかっているのでは ・・ ?
バッファ転送処理の前後で GetByteArrayElements / ReleaseByteArrayElements関数の呼び出しをなくした処理でテストしてみた。
計測した処理時間は以下のようになった。
処理3 AIDL実質呼び出し時間
1回目 31.241秒 0.31241ミリ秒
2回目 29.703秒 0.29703ミリ秒
3回目 31.627秒 0.31627ミリ秒
4回目 30.118秒 0.30118ミリ秒
5回目 29.386秒 0.29386ミリ秒
6回目 29.331秒 0.29331ミリ秒
7回目 29.221秒 0.29221ミリ秒
8回目 29.567秒 0.29567ミリ秒
9回目 29.377秒 0.29377ミリ秒
10回目 29.992秒 0.29992ミリ秒
※ AIDL実質呼び出し時間は処理3時間/100000で算出した。
これらの結果から128バイト分のGetByteArrayElements/ReleaseByteArrayElementsには0.03ミリ秒程度かかっていること、そしてAIDL呼び出しには0.3ミリ秒が必要ことがわかる。
やはりAIDL呼び出し処理の負荷はかなり大きいことを前提でシステム構築する必要がありそうだ。
実際のソースコードはここに置いている。
ソース一式はこちらから
fifo.zip : バッファ転送を行う処理環境一式
fifotest.zip : AIDL呼び出し側テスト環境一式
4月1日に計測したが、エイプリルフールネタは含まれていない(まじめ)。
テストに使用したタブレットはNEC N-08D
http://www1.medias.net/jp/sp/n08d/
テストの動作イメージを下図に記載する。
処理1) AIDL経由でバッファ転送処理を100000回繰り返し呼び出す。
処理2) AIDL経由でバッファ転送処理を1度のみ呼び出し、内部で10000回繰り返す。
計測した処理時間は以下のようになった。
処理1 処理2 AIDL実質呼び出し時間
1回目 34.702秒 0.154秒 0.34548ミリ秒
2回目 34.028秒 0.151秒 0.33877ミリ秒
3回目 34.034秒 0.176秒 0.33858ミリ秒
4回目 33.914秒 0.147秒 0.33767ミリ秒
5回目 33.882秒 0.176秒 0.33706ミリ秒
6回目 33.596秒 0.152秒 0.33444ミリ秒
7回目 33.503秒 0.149秒 0.33354ミリ秒
8回目 34.122秒 0.148秒 0.33974ミリ秒
9回目 33.842秒 0.146秒 0.33696ミリ秒
10回目 33.737秒 0.149秒 0.33588ミリ秒
※ AIDL実質呼び出し時間は(処理1時間-処理2時間)/100000で算出した。
この結果から、AIDL経由での呼び出しには約0.33ミリ秒の時間が必要なことがわかる。
一度関数呼び出すだけで0.3ミリ秒かかるということは、Javaだからということを考慮してもかなり遅い。
そこでもう少し考えてみた。
バッファ転送処理はJNI(C++)で128バイトのデータ転送を行っている。
転送のためにGetByteArrayElementsとReleaseByteArrayElementsを呼び出しているため、AIDL呼び出しではなく、実はこの関数ここで時間がかかっているのでは ・・ ?
バッファ転送処理の前後で GetByteArrayElements / ReleaseByteArrayElements関数の呼び出しをなくした処理でテストしてみた。
計測した処理時間は以下のようになった。
処理3 AIDL実質呼び出し時間
1回目 31.241秒 0.31241ミリ秒
2回目 29.703秒 0.29703ミリ秒
3回目 31.627秒 0.31627ミリ秒
4回目 30.118秒 0.30118ミリ秒
5回目 29.386秒 0.29386ミリ秒
6回目 29.331秒 0.29331ミリ秒
7回目 29.221秒 0.29221ミリ秒
8回目 29.567秒 0.29567ミリ秒
9回目 29.377秒 0.29377ミリ秒
10回目 29.992秒 0.29992ミリ秒
※ AIDL実質呼び出し時間は処理3時間/100000で算出した。
これらの結果から128バイト分のGetByteArrayElements/ReleaseByteArrayElementsには0.03ミリ秒程度かかっていること、そしてAIDL呼び出しには0.3ミリ秒が必要ことがわかる。
やはりAIDL呼び出し処理の負荷はかなり大きいことを前提でシステム構築する必要がありそうだ。
実際のソースコードはここに置いている。
ソース一式はこちらから
fifo.zip : バッファ転送を行う処理環境一式
fifotest.zip : AIDL呼び出し側テスト環境一式
4月1日に計測したが、エイプリルフールネタは含まれていない(まじめ)。
2013年3月28日木曜日
Android アプリケーション間FIFO通信
Androidにて複数アプリ間でデータのやりとりをするためにFIFOサービスを実装してみた。
実際にはAIDLを使えばええやん ・・ なのだが。
たとえばTCP通信をこのサービスで行い、やり取りした情報を他の複数アプリにばら撒くなどという使い方に利用できる。
このようにFIFOサービスを使うことで、複数アプリ間でデータの共通化が可能となる。
FIFOサービスの使用例
FIFOサービスの構成は以下のようにしている。
外部アプリとはAIDLでやり取りを行うために準備した。
実際のFIFOの制御は速度向上のためC++(JNI)で記述している。
またFIFOの本数は、ラッパークラスを配列で複数実装することにより対応できている。
FIFOサービス構成
実際のソースコードはここに置いている。
ソース一式はこちらから
fifo.zip : このFIFOサービスを実現している環境一式
fifotest.zip : このFIFOサービスと接続し、データをやり取りするためのテスト環境一式
fifotestはボタン1でFIFOへのデータ書き出し、ボタン2でFIFOからのデータ読出しを行います。
Androidによるデータの共有化、アプリケーション間FIFO通信などに利用してください。
JNIの部分を変更することで、SharedMemory(共有メモリ)のような使い方もできます。
ソースは理解できるかな? 慣れないとなかなか難しいかもしれませんね。
開発環境全体をダウンロードできるようにしていますので、Eclipseで動作確認してみてください。
動作原理がわかれば簡単です。がんばってトライしてみてください。
2013年3月27日水曜日
Android JNIでライブラリ作成
JNIで作ったC/C++ソースコードの使い回しはみんなどうしているんだろう?
ソースのコピペ?
コピペで新しいファイル作成も面倒なので、ライブラリ化してみた。
■ Android.mkの記述
include $(BUILD_STATIC_LIBRARY)と記述する。
■ Application.mkの記述
APP_OPTIM := release
APP_MODULES := devInf ← モジュール名
// ---------------------------------------------------------
extern void _initDevInf( void );
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := CheckInf
LOCAL_SRC_FILES := checkInf.c ← 新しいプロジェクトのCファイル
LOCAL_STATIC_LIBRARIES := devicelib ← 一時的に生成するライブラリ名
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY) ← .soライブラリを生成する
これでビルドすることで、いつものようにlibsフォルダ内にライブラリファイル(.so)が生成できた。
そうなんやぁ ・・ って感じ。
こんな使い方するのって誰もいないんかな?
ソースのコピペ?
コピペで新しいファイル作成も面倒なので、ライブラリ化してみた。
■ Android.mkの記述
include $(BUILD_STATIC_LIBRARY)と記述する。
BUILD_SHARED_LIBRARYをBUILD_STATIC_LIBRARYに置き換える。
■ Application.mkの記述
APP_OPTIM := release
APP_MODULES := devInf ← モジュール名
モジュール名を定義する。
これでCソースをビルドすると、objフォルダ内にライブラリファイル(libdevinf.a)が生成された。
■ ライブラリの使用
生成されたライブラリを別のプロジェクトで使用してみる。
※新しいCソースには以下の記述を定義しておくことで、ライブラリ内の関数を呼び出すことができる。
// ---------------------------------------------------------
// devinfライブラリ内の関数定義// ---------------------------------------------------------
extern void _initDevInf( void );
上記で生成されたライブラリ(libdevinf.a)をJNIフォルダにコピーし、Android.mkに定義を追記する。
LOCAL_MODULE := devicelib ← 一時的に生成するライブラリ名
LOCAL_SRC_FILES := libdevInf.a ← 上記で生成したライブラリ名include $(PREBUILT_STATIC_LIBRARY)
LOCAL_MODULE := CheckInf
LOCAL_SRC_FILES := checkInf.c ← 新しいプロジェクトのCファイル
LOCAL_STATIC_LIBRARIES := devicelib ← 一時的に生成するライブラリ名
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY) ← .soライブラリを生成する
そうなんやぁ ・・ って感じ。
こんな使い方するのって誰もいないんかな?
Android JNI トラブル(ADT20130219版)
長年システム開発を行っているが、毎回ちょっとしたことでいろいろなトラブルに出会う。
その対策について、忘備録としてこのブログを使用しようと思う。
この忘備録が同様の開発者たちに少しでも役立てばと思う。
■ 今回のトラブル
以前開発したAndroidアプリを新しい環境(adt-bundle-windows-x86-20130219.zip)にて再構築を行った際、JNIで開発したCソースが突然ビルドエラーとなった。
何が悪いのだ? ・・ とにかく悩む。
慣れないWindows版を使用したからか?
慣れた環境(Ubuntu12.04 32bit版)でも同様の環境を構築してみたが、同じくSemantic Errorが発生しビルドできない。
■ ソースファイル
#include <stdlib.h>
#include "com_maxport_memtest_memtest01.h"
JNIEXPORT jboolean JNICALL Java_com_maxport_memtest_funcmemtest( JNIEnv *env, jobject obj )
{
pByteDat = ( char * )malloc( 100 );
return( true );
}
mallocにSemantic Error発生!
何がどう違うのかさっぱりわからない状態で時間だけが経過していった。
※ malloc、memset、read、writeなどに同様のエラーが発生している。
■ 対策
結局はEclipseのビルド環境設定を見直しただけで解決できた。
プロパティ → C/C++ General → Code Analysis
ここで Invalid arguments のエラーチェックを外せばよい。
※ こちら日本語化していないので、 日本語化した場合の表示内容は不明。
Invalid argumentsのチェックを外す。
ビルドエラーはなくなり、無事にビルド完了!
以前の環境(2012年9月あたりにUbuntu12.04上で構築した環境)では問題なかったので、新しい環境でこうなってしまったのだろう。
OSや開発環境のバージョンアップにいつも振り回されてばかりだ ・・・
登録:
投稿 (Atom)