2014年6月18日水曜日



はじめに


これまで3回に渡ってnRF51822ブランクモジュールをARM mbed 対応機器にするための方法について掲載してきましたが、今回から mbedによるBLEプログラミング実践編をスタートいたします。

BluetoothSMARTデバイスをmbed で開発する(4)



はじめに


これまで3回に渡ってnRF51822ブランクモジュールをARM mbed 対応機器にするための方法について掲載してきましたが、今回から mbedによるBLEプログラミング実践編をスタートいたします。

2014年6月4日水曜日



はじめに

前回はARM mbedを用いたソフトウェア開発手法を紹介いたしましたが、今回は連載3回目として mbed対応の要となるハードウェアの作成方法について紹介させていただきます。

BluetoothSMARTデバイスをmbed で開発する(3)



はじめに

前回はARM mbedを用いたソフトウェア開発手法を紹介いたしましたが、今回は連載3回目として mbed対応の要となるハードウェアの作成方法について紹介させていただきます。

2014年5月27日火曜日


はじめに

前回のブログで弊社の取り組みについて紹介させていただきましたが、今回は第二回目として実際にmbedを使った開発について紹介させて頂きます。


BluetoothSMARTデバイスをmbed で開発する(2)


はじめに

前回のブログで弊社の取り組みについて紹介させていただきましたが、今回は第二回目として実際にmbedを使った開発について紹介させて頂きます。


2014年5月23日金曜日


はじめに

NordicのnRF51ブランクモジュールは、法的面でBluetooth SMARTアクセサリ製造への敷居を下げてくれるという期待感から注目されていましたが、モジュール使用にあたって技術面でのハードルが高いところがあり、まだユーザーが増えていないのが現状のようです。

そこで今回は個人レベルでも試作が可能となるような試みとして、nRF51ブランクモジュールのDIP基板化と ARM® mbed™ を使った開発について紹介いたします。

BluetoothSMARTデバイスをmbed で開発する(1)


はじめに

NordicのnRF51ブランクモジュールは、法的面でBluetooth SMARTアクセサリ製造への敷居を下げてくれるという期待感から注目されていましたが、モジュール使用にあたって技術面でのハードルが高いところがあり、まだユーザーが増えていないのが現状のようです。

そこで今回は個人レベルでも試作が可能となるような試みとして、nRF51ブランクモジュールのDIP基板化と ARM® mbed™ を使った開発について紹介いたします。

2014年4月19日土曜日



ついに来ました。やっと来ました。XE16が公開されました。
以前から言われていましたがベースをICS4.0.3から、Kitkat4.4へ変更されています。
追加機能や、変更機能は、すでに他のサイトで紹介されていますので、どのように変わったのか古いバージョンのサンプルソースを利用して調べてみました。


■スクリーン録画って使えるの?

いきなり開発とは関係ない話になります。
スクリーン録画は、Android Kitkat4.4から追加された機能で、その名の通り動作中の動画撮れる機能です。
Google GlassもKitkat 4.4になったんだし、この機能も使えるんじゃないの?って事で試してみました。

実際に録画した動画がこちらになります。


どうでしょう?いい感じではないでしょうか?

Google Glassは内容を人に伝えづらい端末です。
録画した動画を見て頂くことで、Google Glassでの動きも伝えやすくなると思います。


■XE12からの変更点

では、本題です。
XE12から何が変わったのかを探っていきます。

まずは、GDKから。GoogleGlass XE16用のGDKは、アップデート前から配信されています。



実は、サンプルコードも配信される前からXE16用になってます。

※今回は、よく参考に使われるstopwatchを利用しています。


これらをもとに古いバージョンのサンプルを最新のGDKでビルドしてみました。
結果はこんな感じです。



・LiveCardの生成方法

StopwatchService.javaでエラーが発生している箇所を見てみると、LiveCardの生成するためのTimelineManagerクラスが削除されました。

[StopwatchService.java]

XE16以前の記述方法
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            Log.d(TAG, "Publishing LiveCard");
            mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);

            // Keep track of the callback to remove it before unpublishing.
            mCallback = new ChronometerDrawer(this);
            mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mCallback);

            Intent menuIntent = new Intent(this, MenuActivity.class);
            menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));

            mLiveCard.publish(PublishMode.REVEAL);
            Log.d(TAG, "Done publishing LiveCard");
        } else {
            // TODO(alainv): Jump to the LiveCard when API is available.
        }

        return START_STICKY;
    }

こちらが新しいバージョンの記述方法です。
   @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            mLiveCard = new LiveCard(this, LIVE_CARD_TAG);

            // Keep track of the callback to remove it before unpublishing.
            mCallback = new ChronometerDrawer(this);
            mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mCallback);

            Intent menuIntent = new Intent(this, MenuActivity.class);
            menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));
            mLiveCard.attach(this);
            mLiveCard.publish(PublishMode.REVEAL);
        } else {
            mLiveCard.navigate();
        }

        return START_STICKY;
    }


TimelineManagerからLiveCardを生成するのではなく、LiveCardを直接生成する方法に変わっています。

LiveCardの生成方法を変更することで、とりあえずはビルドが通る状態となりました。
では早速、Glassで動作確認をしてみます。


・音声で起動しない

インストールした後、「start a stopwatch」と話しても起動してくれません。
音声起動どころか、音声起動の一覧にすら表示されていません。

調べてみると音声起動の設定方法が変わっていました。
今回のバージョンより、決まった音声のみの起動可能となってます。

それだとテストも出来ないじゃないかということで、以下のuses permissionを利用することで今までと同じように音声での起動も可能となります。

<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />   


ただし、開発時のオプションのため、リリース時には、Googleの承認が必要となりそうです。
音声起動の部分は、今後公開するうえでネックになりそうに思います。



これで起動もできたので、ストップウォッチの動作を確認します。



動作も問題なしだったので終了したところ・・


まさかの異常終了。
エラーログを見るとこんな感じに。



・openOptionMenuの呼び出しタイミング

問題を調べてみると、openOptionMenuが呼び出されるタイミングが変わっていました。


[MenuActivity.java]

XE16以前の記述方法
@Override
    public void onResume() {
        super.onResume();
        openOptionsMenu();
    }

こちらが新しいバージョンの記述方法です。
@Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        openOptionsMenu();
    }


ここまで来ると以前と同じように動作するようになりました。





今回調査をしてみてLiveCard周りの変更が大きいと感じました。
説明できていませんが、追加されている部分も多くあります(attachやnavigateなど)
音声起動は、着々と一般販売に向けて制限しているのかなという感じです。

Bluetooth周りも大幅に変わったと聞きます。
以前のバージョンでは、かなり苦労したので今回のバージョンアップで、少しでも素直になってくれたらと期待しています。
LiveCardの追加分も含めて、別の機会で報告できればと思います。





㈱ブリリアントサービス 大阪開発部 開発課 田中雅也



[コラム] Google Glass XE16 サンプルコードから見る変更点



ついに来ました。やっと来ました。XE16が公開されました。
以前から言われていましたがベースをICS4.0.3から、Kitkat4.4へ変更されています。
追加機能や、変更機能は、すでに他のサイトで紹介されていますので、どのように変わったのか古いバージョンのサンプルソースを利用して調べてみました。


■スクリーン録画って使えるの?

いきなり開発とは関係ない話になります。
スクリーン録画は、Android Kitkat4.4から追加された機能で、その名の通り動作中の動画撮れる機能です。
Google GlassもKitkat 4.4になったんだし、この機能も使えるんじゃないの?って事で試してみました。

実際に録画した動画がこちらになります。


どうでしょう?いい感じではないでしょうか?

Google Glassは内容を人に伝えづらい端末です。
録画した動画を見て頂くことで、Google Glassでの動きも伝えやすくなると思います。


■XE12からの変更点

では、本題です。
XE12から何が変わったのかを探っていきます。

まずは、GDKから。GoogleGlass XE16用のGDKは、アップデート前から配信されています。



実は、サンプルコードも配信される前からXE16用になってます。

※今回は、よく参考に使われるstopwatchを利用しています。


これらをもとに古いバージョンのサンプルを最新のGDKでビルドしてみました。
結果はこんな感じです。



・LiveCardの生成方法

StopwatchService.javaでエラーが発生している箇所を見てみると、LiveCardの生成するためのTimelineManagerクラスが削除されました。

[StopwatchService.java]

XE16以前の記述方法
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            Log.d(TAG, "Publishing LiveCard");
            mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);

            // Keep track of the callback to remove it before unpublishing.
            mCallback = new ChronometerDrawer(this);
            mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mCallback);

            Intent menuIntent = new Intent(this, MenuActivity.class);
            menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));

            mLiveCard.publish(PublishMode.REVEAL);
            Log.d(TAG, "Done publishing LiveCard");
        } else {
            // TODO(alainv): Jump to the LiveCard when API is available.
        }

        return START_STICKY;
    }

こちらが新しいバージョンの記述方法です。
   @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            mLiveCard = new LiveCard(this, LIVE_CARD_TAG);

            // Keep track of the callback to remove it before unpublishing.
            mCallback = new ChronometerDrawer(this);
            mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mCallback);

            Intent menuIntent = new Intent(this, MenuActivity.class);
            menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));
            mLiveCard.attach(this);
            mLiveCard.publish(PublishMode.REVEAL);
        } else {
            mLiveCard.navigate();
        }

        return START_STICKY;
    }


TimelineManagerからLiveCardを生成するのではなく、LiveCardを直接生成する方法に変わっています。

LiveCardの生成方法を変更することで、とりあえずはビルドが通る状態となりました。
では早速、Glassで動作確認をしてみます。


・音声で起動しない

インストールした後、「start a stopwatch」と話しても起動してくれません。
音声起動どころか、音声起動の一覧にすら表示されていません。

調べてみると音声起動の設定方法が変わっていました。
今回のバージョンより、決まった音声のみの起動可能となってます。

それだとテストも出来ないじゃないかということで、以下のuses permissionを利用することで今までと同じように音声での起動も可能となります。

<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />   


ただし、開発時のオプションのため、リリース時には、Googleの承認が必要となりそうです。
音声起動の部分は、今後公開するうえでネックになりそうに思います。



これで起動もできたので、ストップウォッチの動作を確認します。



動作も問題なしだったので終了したところ・・


まさかの異常終了。
エラーログを見るとこんな感じに。



・openOptionMenuの呼び出しタイミング

問題を調べてみると、openOptionMenuが呼び出されるタイミングが変わっていました。


[MenuActivity.java]

XE16以前の記述方法
@Override
    public void onResume() {
        super.onResume();
        openOptionsMenu();
    }

こちらが新しいバージョンの記述方法です。
@Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        openOptionsMenu();
    }


ここまで来ると以前と同じように動作するようになりました。





今回調査をしてみてLiveCard周りの変更が大きいと感じました。
説明できていませんが、追加されている部分も多くあります(attachやnavigateなど)
音声起動は、着々と一般販売に向けて制限しているのかなという感じです。

Bluetooth周りも大幅に変わったと聞きます。
以前のバージョンでは、かなり苦労したので今回のバージョンアップで、少しでも素直になってくれたらと期待しています。
LiveCardの追加分も含めて、別の機会で報告できればと思います。





㈱ブリリアントサービス 大阪開発部 開発課 田中雅也



2014年4月17日木曜日


GDKで動的なGlasswareを作成する方法には、LiveCardを使用する方法とImmersionという方法が存在します。その二つの方法で同じアプリを作成してみたところ、処理の構築に大きな差異があることがわかりました。

その具体的な内容については本文から。



GDKでの動的なGlassware作成


GDKで動的なGlasswareを作成する方法には、LiveCardを使用する方法とImmersionという方法が存在します。その二つの方法で同じアプリを作成してみたところ、処理の構築に大きな差異があることがわかりました。

その具体的な内容については本文から。



2014年3月20日木曜日



f:id:bs-android:20140319172604p:image

早くも発売が待ち遠しいAndroid Wearの端末ですが、端末を買ってから環境を整えていたら開発者として楽しめません。

エミュレータを使って開発ができるので環境構築手順を紹介します。

Android Wear Developer Preview 開発環境構築



f:id:bs-android:20140319172604p:image

早くも発売が待ち遠しいAndroid Wearの端末ですが、端末を買ってから環境を整えていたら開発者として楽しめません。

エミュレータを使って開発ができるので環境構築手順を紹介します。



f:id:bs-android:20140319135838j:image

2週間近く前にGoogleのSundar Pichai氏がSXSWのイベントでAndroidのウェアラブル機器のSDKをリリースするという話をしていたのですが、宣言通りに開発者向けプレビュー版のSDKが本日公開されました。

公式ブログでのAndroid Wear発表

Android Wear開発者向けサイト

Android Wearとは


Android WearとはAndroid搭載スマートフォンと連携して動作するウェアラブルデバイスのことを指すようです。

現段階では腕時計だけが対象のようですが、今後他のウェアラブル機器にも広げていくとのこと。

音声でのテキスト入力、タッチパネルでの操作が可能なようです。

詳細なハードウェア仕様はまだ公開されていません。




恐らく6/25-6/26にサンフランシスコで開催されるGoogle I/O 2014でデバイスがお目見えすることになると思います。




モトローラが夏にAndroid Wear端末Moto 360を発売すると発表しているので恐らくこのモデルがGoogle I/O参加者に配布されることになるのではないかと予想しています。

まずは利用シーンの紹介動画。


D

開発者向け動画


D

下の画像は動画から抜き出したものですが、Google Nowで使える機能がほとんど使えるようです。天気予報、経路検索、音声入力でHangoutでテキストチャットもできている模様。


f:id:bs-android:20140319144846p:image:w360

f:id:bs-android:20140319144845p:image:w360

f:id:bs-android:20140319144844p:image:w360

f:id:bs-android:20140319144843p:image:w360

f:id:bs-android:20140319144842p:image:w360

f:id:bs-android:20140319144840p:image:w360

f:id:bs-android:20140319144841p:image:w360

f:id:bs-android:20140319144839p:image:w360


UIの動作イメージはこんな感じです。

画面が小さいので基本操作はスワイプ。音声入力にも対応しています。

「Ok google」と話しかけると、そこからアプリとインターネットへの道が開きます。


f:id:bs-android:20140319153819g:image




f:id:bs-android:20140319153820g:image




f:id:bs-android:20140319154729g:image


まずは概要だけお届けしましたが、開発者視点の記事を随時更新していきますのでお楽しみに。







ちなみにシンクロニシティなのかどうかわかりませんが、偶然にも(?)2日ほど前にTizen陣営からもTizen Software Developer Kit for Wearablesというスマートウォッチ向けのSDKがリリースされています。




[コラム] ウェアラブル機器開発の本命、Android Wear登場



f:id:bs-android:20140319135838j:image

2週間近く前にGoogleのSundar Pichai氏がSXSWのイベントでAndroidのウェアラブル機器のSDKをリリースするという話をしていたのですが、宣言通りに開発者向けプレビュー版のSDKが本日公開されました。

公式ブログでのAndroid Wear発表

Android Wear開発者向けサイト

Android Wearとは


Android WearとはAndroid搭載スマートフォンと連携して動作するウェアラブルデバイスのことを指すようです。

現段階では腕時計だけが対象のようですが、今後他のウェアラブル機器にも広げていくとのこと。

音声でのテキスト入力、タッチパネルでの操作が可能なようです。

詳細なハードウェア仕様はまだ公開されていません。




恐らく6/25-6/26にサンフランシスコで開催されるGoogle I/O 2014でデバイスがお目見えすることになると思います。




モトローラが夏にAndroid Wear端末Moto 360を発売すると発表しているので恐らくこのモデルがGoogle I/O参加者に配布されることになるのではないかと予想しています。

まずは利用シーンの紹介動画。


D

開発者向け動画


D

下の画像は動画から抜き出したものですが、Google Nowで使える機能がほとんど使えるようです。天気予報、経路検索、音声入力でHangoutでテキストチャットもできている模様。


f:id:bs-android:20140319144846p:image:w360

f:id:bs-android:20140319144845p:image:w360

f:id:bs-android:20140319144844p:image:w360

f:id:bs-android:20140319144843p:image:w360

f:id:bs-android:20140319144842p:image:w360

f:id:bs-android:20140319144840p:image:w360

f:id:bs-android:20140319144841p:image:w360

f:id:bs-android:20140319144839p:image:w360


UIの動作イメージはこんな感じです。

画面が小さいので基本操作はスワイプ。音声入力にも対応しています。

「Ok google」と話しかけると、そこからアプリとインターネットへの道が開きます。


f:id:bs-android:20140319153819g:image




f:id:bs-android:20140319153820g:image




f:id:bs-android:20140319154729g:image


まずは概要だけお届けしましたが、開発者視点の記事を随時更新していきますのでお楽しみに。







ちなみにシンクロニシティなのかどうかわかりませんが、偶然にも(?)2日ほど前にTizen陣営からもTizen Software Developer Kit for Wearablesというスマートウォッチ向けのSDKがリリースされています。




2014年2月20日木曜日



Glassを身につけている人の視線(カメラプレビュー)をリアルタイムに共有できたらとても便利と思いませんか?

更にお互いに何かのアクションをやりとりできたらどんなに素敵でしょう。さまざまな仕事やエンターテイメントに応用できるはずです。

ということで、Glass の視線をiPadで共有し、ついでに、iPadからGlassに対して指示を送るサンプルを作ってみました。「ここを見て!」という指示が飛ぶようにします。



アプリの流れは以下のようになります。


GoogleGlassの視線(カメラプレビュー)をiPad でリアルタイムに共有して、かつ、指示を送ってみる その一



Glassを身につけている人の視線(カメラプレビュー)をリアルタイムに共有できたらとても便利と思いませんか?

更にお互いに何かのアクションをやりとりできたらどんなに素敵でしょう。さまざまな仕事やエンターテイメントに応用できるはずです。

ということで、Glass の視線をiPadで共有し、ついでに、iPadからGlassに対して指示を送るサンプルを作ってみました。「ここを見て!」という指示が飛ぶようにします。



アプリの流れは以下のようになります。


2014年2月14日金曜日



以前GDKでActivityを多様することは本体の発熱量が高くなるに少し触れましたが、今回はその発熱対策として放熱板の取り付けを行ってみました。

元々Google Glassには既存で放熱板が取り付けられています。

しかしコストの高いアプリを作成し、動作を続けるとタップやスワイプなどを行う右側部分(装着時)のフレームの発熱が非常に高くなることがわかりました。


f:id:bs-android:20140213193033j:image:w360



ピンク:既存の耐熱板。Glassフレームを囲うように装着してある。

 :発熱が最も高い部分。今回はここに自作の耐熱板を装着する。




少し温かくなる程度であれば問題ないのですが、カメラ機能を使い続けるようなコストの高いアプリを動作させ続けると、Glassをかけ続けることも辛いほどの発熱量となります。

そこで既存の放熱板だけでは不足な発熱の対策としてオリジナルの放熱板を取り付けることを試みました。




用意したもの




  • 熱伝導性シリコン

  • 熱伝導性接着剤

  • コイン

  • プラスチックの線

  • ハサミ

  • ペンチ

f:id:bs-android:20140213193034j:image:w360







手順


1)シリコンを発熱対策を行いたいフレームのサイズに合わせてカットし、熱伝導性の接着剤を使い重ね合わせます。

f:id:bs-android:20140213193035j:image:w360




2)更に放熱度をあげるため、重ねたシリコンの間にコインを挟みます。

f:id:bs-android:20140213193036j:image:w360




3)2)で作成したものをGlassの放熱を行いたい部分に装着します。

このとき、放熱板とGlassに隙間ができると放熱効果が下がるため、しっかり密着させることが重要。

f:id:bs-android:20140213193037j:image:w360







装着イメージ


f:id:bs-android:20140213193038j:image:w360

放熱板を装着したことによる違和感は特に気にならず。







成果


オリジナルの放熱板を取り付けることにより、以前に感じていた発熱を抑えることができました。

またカメラビューを使い続けるようなアプリをGlassで動作させ続けた際の動作時間を以前の約倍近くまで延ばすことができました。







今回苦労した点


Glassに放熱板の密着度を意識しながら取り付けたことぐらいです。

ですが、これが重要です!!!!




今回の放熱板の取り付けにより発熱対策は行いましたが、より多様な機能を搭載したアプリを開発するには設計段階からの省エネ対策が必要となります。




[Tips] Google Glassの発熱対策



以前GDKでActivityを多様することは本体の発熱量が高くなるに少し触れましたが、今回はその発熱対策として放熱板の取り付けを行ってみました。

元々Google Glassには既存で放熱板が取り付けられています。

しかしコストの高いアプリを作成し、動作を続けるとタップやスワイプなどを行う右側部分(装着時)のフレームの発熱が非常に高くなることがわかりました。


f:id:bs-android:20140213193033j:image:w360



ピンク:既存の耐熱板。Glassフレームを囲うように装着してある。

 :発熱が最も高い部分。今回はここに自作の耐熱板を装着する。




少し温かくなる程度であれば問題ないのですが、カメラ機能を使い続けるようなコストの高いアプリを動作させ続けると、Glassをかけ続けることも辛いほどの発熱量となります。

そこで既存の放熱板だけでは不足な発熱の対策としてオリジナルの放熱板を取り付けることを試みました。




用意したもの




  • 熱伝導性シリコン

  • 熱伝導性接着剤

  • コイン

  • プラスチックの線

  • ハサミ

  • ペンチ

f:id:bs-android:20140213193034j:image:w360







手順


1)シリコンを発熱対策を行いたいフレームのサイズに合わせてカットし、熱伝導性の接着剤を使い重ね合わせます。

f:id:bs-android:20140213193035j:image:w360




2)更に放熱度をあげるため、重ねたシリコンの間にコインを挟みます。

f:id:bs-android:20140213193036j:image:w360




3)2)で作成したものをGlassの放熱を行いたい部分に装着します。

このとき、放熱板とGlassに隙間ができると放熱効果が下がるため、しっかり密着させることが重要。

f:id:bs-android:20140213193037j:image:w360







装着イメージ


f:id:bs-android:20140213193038j:image:w360

放熱板を装着したことによる違和感は特に気にならず。







成果


オリジナルの放熱板を取り付けることにより、以前に感じていた発熱を抑えることができました。

またカメラビューを使い続けるようなアプリをGlassで動作させ続けた際の動作時間を以前の約倍近くまで延ばすことができました。







今回苦労した点


Glassに放熱板の密着度を意識しながら取り付けたことぐらいです。

ですが、これが重要です!!!!




今回の放熱板の取り付けにより発熱対策は行いましたが、より多様な機能を搭載したアプリを開発するには設計段階からの省エネ対策が必要となります。




2014年2月13日木曜日


2014年2月の日本アンドロイドの会定例会に参加してきました。

https://www.android-group.jp/event/event28.html

iBeaconとはどんなもので、アンドロイドで実現する場合に注意すべきことは何かなどを、この方面で活躍されている方を招いて勉強するという内容でした。

まず、今度の2/15、16に会津でBLEハッカソンを企画されている、Aka Beacon で有名なGClue の佐々木陽氏が、iBeacon とは、UUID、Major、Minor でビーコンを区別し、Immediate/Near/Far/Unknown などの近さが取得できるものですよ、ということを自作したデバイスを使ってデモを行いながら、非常に軽やかに説明されました。

また、iOSのバックグラウンド処理についても触れて、アプリがバックグラウンドにいてもRegion IN/OUTのイベントを受信でき、15秒間は動作可能ということも述べられていました。結局、もっとバックグラウンド動作を伸ばす方法はあるみたいですが…。

アンドロイドは、各アプリがビーコンを監視する部分を独自でもつため、ビーコンを利用するアプリが立ち上がるほど、電力消費が大きくなるとのこと。対して、iOSは、フレームワーク部分がビーコンの監視を行ってくれているので、ビーコンを使うアプリがたくさんいても省電力になっているとのこと。だから、アンドロイドでもビーコンを扱うサービスを作り、省電力な設計を行う必要があるとおっしゃっていました。

あとは、エコシステム、Appcessoryを中心とする最近のビジネス状況について、BLEデバイスのモジュール化のベンチャーが増えていることなどを説明してくれました。

続いて、Applixで研究開発をされている日向さんがビーコンの電波特性について、非常にわかりやすく解説してくれました。屋内測位をやっていると、電波特性というものに敏感になるもので、なんでこんなに状況によって電波強度がかわるのか深く知りたくなってきます。日向さんの調べたところによると、床や壁などに当たって跳ね返ってくる反射波との干渉により、場所によって電波の強弱が変わってしまうということです。また、電波強度と距離の関係式も、2、3mくらいまでなら大体合っているが、距離が遠くなるに連れて、実際の値とのずれが大きくなってくるとのこと。屋内測位をやったときもFarのビーコンは無視すると非常にうまく行きましたから、納得です。日向さんの考えでは、RSSIからもとめる距離の精度も対数をとった値なら実用に耐えられるのでは、とのこと。

あとのお二人は、iBeaconを使った事例でした。

元頓知ドットさんのおでかけスクラップサービス"tab"は、失敗事例などいくつか紹介しており、非常に参考になりました。

残念ながら、帰阪するため参加できたのはここまででした。

iBeaconでブームとなったBLEの流れですが、アンドロイドでちゃんとしたサービスが展開されるのはまだまだ先なのかなという印象を受けました。

[コラム] 日本アンドロイドの会2月定例会に参加してきました。


2014年2月の日本アンドロイドの会定例会に参加してきました。

https://www.android-group.jp/event/event28.html

iBeaconとはどんなもので、アンドロイドで実現する場合に注意すべきことは何かなどを、この方面で活躍されている方を招いて勉強するという内容でした。

まず、今度の2/15、16に会津でBLEハッカソンを企画されている、Aka Beacon で有名なGClue の佐々木陽氏が、iBeacon とは、UUID、Major、Minor でビーコンを区別し、Immediate/Near/Far/Unknown などの近さが取得できるものですよ、ということを自作したデバイスを使ってデモを行いながら、非常に軽やかに説明されました。

また、iOSのバックグラウンド処理についても触れて、アプリがバックグラウンドにいてもRegion IN/OUTのイベントを受信でき、15秒間は動作可能ということも述べられていました。結局、もっとバックグラウンド動作を伸ばす方法はあるみたいですが…。

アンドロイドは、各アプリがビーコンを監視する部分を独自でもつため、ビーコンを利用するアプリが立ち上がるほど、電力消費が大きくなるとのこと。対して、iOSは、フレームワーク部分がビーコンの監視を行ってくれているので、ビーコンを使うアプリがたくさんいても省電力になっているとのこと。だから、アンドロイドでもビーコンを扱うサービスを作り、省電力な設計を行う必要があるとおっしゃっていました。

あとは、エコシステム、Appcessoryを中心とする最近のビジネス状況について、BLEデバイスのモジュール化のベンチャーが増えていることなどを説明してくれました。

続いて、Applixで研究開発をされている日向さんがビーコンの電波特性について、非常にわかりやすく解説してくれました。屋内測位をやっていると、電波特性というものに敏感になるもので、なんでこんなに状況によって電波強度がかわるのか深く知りたくなってきます。日向さんの調べたところによると、床や壁などに当たって跳ね返ってくる反射波との干渉により、場所によって電波の強弱が変わってしまうということです。また、電波強度と距離の関係式も、2、3mくらいまでなら大体合っているが、距離が遠くなるに連れて、実際の値とのずれが大きくなってくるとのこと。屋内測位をやったときもFarのビーコンは無視すると非常にうまく行きましたから、納得です。日向さんの考えでは、RSSIからもとめる距離の精度も対数をとった値なら実用に耐えられるのでは、とのこと。

あとのお二人は、iBeaconを使った事例でした。

元頓知ドットさんのおでかけスクラップサービス"tab"は、失敗事例などいくつか紹介しており、非常に参考になりました。

残念ながら、帰阪するため参加できたのはここまででした。

iBeaconでブームとなったBLEの流れですが、アンドロイドでちゃんとしたサービスが展開されるのはまだまだ先なのかなという印象を受けました。

2014年1月28日火曜日



GDKでは、以前お伝えしたCardの仕組みを使わずにAndroidと同様にActivityを使ってアプリを構築することができます。



注意点としては以下があります。



  • 640 × 360 の解像度

  • スワイプダウンが戻るボタンに該当する

  • Androidのようなタッチ操作はできない

しかしActivityだけではアプリが timeline 上に表示されない為、ユーザーがアプリを起動する手段がありません。そこで、アプリ起動用Serviceを用意してonStartCommand()のタイミングで任意のアクティビティを起動してやる必要があります。

なんだかとても面倒に感じますが、とても簡単。

まずサービスクラスを用意します。

単純にアクティビティを起動するだけのサービスクラスに必要なコードはたったこれだけ。

public class HelloService extends Service {
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Intent aIntent = new Intent();
        aIntent.setClassName("com.example.helloactivity","com.example.helloactivity.MainActivity");
        aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
        startActivity(aIntent);
        return START_STICKY;
    }
}


あとは timeline からサービスを呼ぶようにマニフェストファイルを設定するだけ。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloactivity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
         android:icon="@drawable/ic_launcher"
            android:name="com.example.helloactivity.MainActivity"
            android:label="@string/app_name" >
        </activity>
        <service
            android:name="com.example.helloactivity.HelloService"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />
        </service>
    </application>
</manifest>


この intent-filter と meta-data が重要で、これを記述することによってサービスが timeline 上に表示されるようになります。

            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />


これだけで、Androidと同様のActivityを使ったアプリをGlassで実現することができます。

しかし、AndroidアプリをGlassに簡単に移植できる、とは考えないで下さい

現時点で Activity は Glass にはコストが高く、非常に動作が重くなり、本体の発熱も凄いです。

現時点では、Glass に Activity を使うのは良い選択肢ではないと考えます。

それを示すように、Activity を使って描画を行っているサンプルは Google から提供されていません。

そもそもソースコードも公開されてませんし、Glass は Android と似て非なるもの なのです。




GDKでActivityを使ってみる



GDKでは、以前お伝えしたCardの仕組みを使わずにAndroidと同様にActivityを使ってアプリを構築することができます。



注意点としては以下があります。



  • 640 × 360 の解像度

  • スワイプダウンが戻るボタンに該当する

  • Androidのようなタッチ操作はできない

しかしActivityだけではアプリが timeline 上に表示されない為、ユーザーがアプリを起動する手段がありません。そこで、アプリ起動用Serviceを用意してonStartCommand()のタイミングで任意のアクティビティを起動してやる必要があります。

なんだかとても面倒に感じますが、とても簡単。

まずサービスクラスを用意します。

単純にアクティビティを起動するだけのサービスクラスに必要なコードはたったこれだけ。

public class HelloService extends Service {
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Intent aIntent = new Intent();
        aIntent.setClassName("com.example.helloactivity","com.example.helloactivity.MainActivity");
        aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
        startActivity(aIntent);
        return START_STICKY;
    }
}


あとは timeline からサービスを呼ぶようにマニフェストファイルを設定するだけ。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloactivity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
         android:icon="@drawable/ic_launcher"
            android:name="com.example.helloactivity.MainActivity"
            android:label="@string/app_name" >
        </activity>
        <service
            android:name="com.example.helloactivity.HelloService"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />
        </service>
    </application>
</manifest>


この intent-filter と meta-data が重要で、これを記述することによってサービスが timeline 上に表示されるようになります。

            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />


これだけで、Androidと同様のActivityを使ったアプリをGlassで実現することができます。

しかし、AndroidアプリをGlassに簡単に移植できる、とは考えないで下さい

現時点で Activity は Glass にはコストが高く、非常に動作が重くなり、本体の発熱も凄いです。

現時点では、Glass に Activity を使うのは良い選択肢ではないと考えます。

それを示すように、Activity を使って描画を行っているサンプルは Google から提供されていません。

そもそもソースコードも公開されてませんし、Glass は Android と似て非なるもの なのです。









本ブログ「屋内測位をやってみました」で、始めた屋内測位ですが、あれからいろいろやってみて、だいぶまともに動くようになってきました。今回はある会議室にビーコンをだいたい3m四方に12個配置しました。使用したビーコンは、Estimote社のものを使っています。このビーコン出力が弱いため、精度を出すには3mという短い間隔で置くしかありませんでした。使用した測位アルゴリズムも、トリラテレーション(Trilateration)ではなく、近辺のビーコン位置にRSSI値をもとにした加重平均をとる方法を採用しました。

では、実際の実験の様子をご覧ください。

iBeaconで屋内測位成功のヒントをつかんだ!






本ブログ「屋内測位をやってみました」で、始めた屋内測位ですが、あれからいろいろやってみて、だいぶまともに動くようになってきました。今回はある会議室にビーコンをだいたい3m四方に12個配置しました。使用したビーコンは、Estimote社のものを使っています。このビーコン出力が弱いため、精度を出すには3mという短い間隔で置くしかありませんでした。使用した測位アルゴリズムも、トリラテレーション(Trilateration)ではなく、近辺のビーコン位置にRSSI値をもとにした加重平均をとる方法を採用しました。

では、実際の実験の様子をご覧ください。

2014年1月15日水曜日



Google からGlass Development Kit(以後GDK)が発表されてしばらく経ちました。

合わせて開発者用Glassの販売も行われ、今後市場投入に向けての動きが活発になることが予想されます。

しかしこの開発者用Glass、2014年1月時点で日本からは購入することができません。

USAでも開発者向けの招待メールでしか購入ができないようになっています。

弊社は現地支社がある為、いくつか購入することができました。

Glassを使った開発ノウハウが徐々に溜まってきたので、GDKでHelloWorldを書く方法をお伝えします。



さて、まず一言。

HelloWorld を書くのにこんなに苦労したのは久しぶりでした

完成されたSDKであれば普通、HelloWorldというのはプロジェクトを新規作成すると自動的に生成されるスケルトンプロジェクトに、ちょちょいと追記するだけで簡単に作れるものなのですが、現在のGDK(Rev.2)にはスケルトンコードを出力する機能がありません

従って今回は、GDKの中に含まれるサンプルコードをリファクタリングしながらHelloWorldを作ります。

Google Glassの開発環境


Glassの開発環境は基本的にAndroidと同じで、IDEはEclipseを使うのが最も簡単でしょう。

Android SDK Managerから Android 4.0.3 > GDK を選択して開発環境をインストールします。

f:id:bs-android:20140110095919p:image:w640

HelloWorldを作ってみる


それではGDKに含まれるサンプルコードをリファクタリングしながらHelloWorldを作ってみます。

新規プロジェクト > Android Sample Project > GDK > Timer を選択します。最後の画面でプロジェクト名をHelloWorldに変えておきます。

f:id:bs-android:20140110095920p:image:w360

f:id:bs-android:20140110095921p:image:w360

f:id:bs-android:20140110095922p:image:w360

このサンプルはその名の通りタイマーアプリで、設定した時間をカウントダウンすることができます。

まず、アプリがどのような動作をするか確認します。

遷移図を作りました。

f:id:bs-android:20140110095924j:image:w640

Glassはタップによる文字入力ができませんので入力項目は全て選択式になります。従って、シンプルなアプリですが画面数はとても多くなる傾向にあります。

Timerサンプルを解析してみる


次はTimerサンプルのコードを見て行きます。

まずはManifestから。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.android.glass.sample.timer"
    android:versionCode="2"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_timer"
        android:label="@string/app_name" >

        <activity
            android:name="com.google.android.glass.sample.timer.MenuActivity"
            android:label="@string/app_name"
            android:theme="@style/MenuTheme"
            android:enabled="true" >
        </activity>

        <activity
            android:name="com.google.android.glass.sample.timer.SetTimerActivity"
            android:label="@string/app_name"
            android:enabled="true" >
        </activity>

        <activity
            android:name="com.google.android.glass.sample.timer.SelectValueActivity"
            android:label="@string/app_name"
            android:enabled="true" >
        </activity>

        <service
            android:name="com.google.android.glass.sample.timer.TimerService"
            android:icon="@drawable/ic_timer"
            android:label="@string/app_name"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />
        </service>

    </application>

</manifest>


Activity が三つにServiceが一つ宣言されています。

こんなに小さなアプリでActivityが三つもあるのは何故か?

Glassでは基本的にActivityはコンテンツを描画する目的では無くメニューを表示する目的で使われます。従って、メニュー(設定項目や選択項目)が増えるとActivityがどんどん増えていく傾向があります。

Service内のmeta-dataは音声認識によるアプリ起動をサポートします。

次はソースコードを見て行きます。



  • MenuActivity.java

  • SelectValueActivity.java

  • SelectValueScrollAdapter.java

  • SetTimerActivity.java

  • SetTimerScrollAdapter.java

  • Timer.java

  • TimerDrawer.java

  • TimerService.java

  • TimerView.java

この中で最低限必要なクラスは以下です。



  • MenuActivity.java

  • TimerDrawer.java

  • TimerService.java

一つのGlassアプリには必ず一つのサービスが必要です。

サービスである為、アプリを終了する為のメニューが必要となるでしょう。必然的にメニューを表示するActivityも一つは必要となります。

さっき、Activityはメニューを表示する為に使うと説明しました。では、肝心のコンテンツはどのように描画するか?

GlassではCardというAndroidには無い仕組みが有ります。

Cardとは


Androidでは一つのActivityで一画面を表現しますが、Glassでは一つのCardで一つの画面を表現することができます。

CardにはStatic CardLive Cardの二種類があり、画面の更新頻度に応じて使い分けるとDocには書かれています。

TimerサンプルはLive Cardを利用している為、今回はLive Cardを使うことにします。

Live Cardは以下のような仕組みになっています。

http://developers.google.com/glass/images/diagrams/live-card-service.png

Glassではアプリ一覧が並ぶUIの事をTimelineと呼びます。

Timeline からアプリのサービスが起動し、サービスでLive Cardを生成しコンテンツの描画を行います。

HelloWorldを作ってみた


Timerサンプルを元に作成したHelloWorldのプロジェクト一式はこちら




重要なのはTimerServiceのonStartCommand()で、それ以外はAndroidと全く同じです。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (mLiveCard == null) {
        //LiveCardを生成したい
        mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);

        //レンダリング用Drawerを追加したい
        mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mTimerDrawer);
        
        //Menu用Activityの生成と追加をしたい
        Intent menuIntent = new Intent(this, MenuActivity.class);
        menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));

        //LiveCardを表示したい
        mLiveCard.publish(PublishMode.REVEAL);
    } else {
        // TODO(alainv): Jump to the LiveCard when API is available.
    }

    return START_STICKY;
}


尚、Cardを使わずAndroidと同様にActivityのみでアプリを構築する方法もあります。

しかしこの場合、そのままではTimelineからアプリを起動することができない為、アプリを起動する為だけのGlassアプリを用意する必要があります。これに関してはまた別の機会に書きます。

Glassの開発難易度


残念ながら現時点ではGlass用のシミュレータはありません。実機が無いとアプリのテストができない為、早急なシミュレータ環境の提供を期待するばかりです。

コードを書く事だけを見れば、Cardの概念さえ理解すれば後はAndroidとほとんど同じである為、Androidアプリ開発経験者はスムーズに開発を行うことができるでしょう。

しかし、実際にGlassを身につけるとよくわかるのですが、この最低限のアプリケーションでも、起動すると本体が非常に熱くなり、継続した装着が困難になります。

Glassで実用的なアプリケーションを構築する為には高度な省エネのスキルが要求されることでしょう。

しかし、Glassはソースコードが公開されていません。その為、基本的に Java 層で省エネを実現する必要があります。

実験的なアプリケーションはAndroidの延長線上で作れるものの、現時点のGlassの性能で実用的なアプリケーションをFixする為には非常に高度な開発スキルが求められると考えます。

Java で省エネって、アメ車に低燃費を求めるようなもんですよね




GDKでHelloWorldを作ってみる



Google からGlass Development Kit(以後GDK)が発表されてしばらく経ちました。

合わせて開発者用Glassの販売も行われ、今後市場投入に向けての動きが活発になることが予想されます。

しかしこの開発者用Glass、2014年1月時点で日本からは購入することができません。

USAでも開発者向けの招待メールでしか購入ができないようになっています。

弊社は現地支社がある為、いくつか購入することができました。

Glassを使った開発ノウハウが徐々に溜まってきたので、GDKでHelloWorldを書く方法をお伝えします。



さて、まず一言。

HelloWorld を書くのにこんなに苦労したのは久しぶりでした

完成されたSDKであれば普通、HelloWorldというのはプロジェクトを新規作成すると自動的に生成されるスケルトンプロジェクトに、ちょちょいと追記するだけで簡単に作れるものなのですが、現在のGDK(Rev.2)にはスケルトンコードを出力する機能がありません

従って今回は、GDKの中に含まれるサンプルコードをリファクタリングしながらHelloWorldを作ります。

Google Glassの開発環境


Glassの開発環境は基本的にAndroidと同じで、IDEはEclipseを使うのが最も簡単でしょう。

Android SDK Managerから Android 4.0.3 > GDK を選択して開発環境をインストールします。

f:id:bs-android:20140110095919p:image:w640

HelloWorldを作ってみる


それではGDKに含まれるサンプルコードをリファクタリングしながらHelloWorldを作ってみます。

新規プロジェクト > Android Sample Project > GDK > Timer を選択します。最後の画面でプロジェクト名をHelloWorldに変えておきます。

f:id:bs-android:20140110095920p:image:w360

f:id:bs-android:20140110095921p:image:w360

f:id:bs-android:20140110095922p:image:w360

このサンプルはその名の通りタイマーアプリで、設定した時間をカウントダウンすることができます。

まず、アプリがどのような動作をするか確認します。

遷移図を作りました。

f:id:bs-android:20140110095924j:image:w640

Glassはタップによる文字入力ができませんので入力項目は全て選択式になります。従って、シンプルなアプリですが画面数はとても多くなる傾向にあります。

Timerサンプルを解析してみる


次はTimerサンプルのコードを見て行きます。

まずはManifestから。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.android.glass.sample.timer"
    android:versionCode="2"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_timer"
        android:label="@string/app_name" >

        <activity
            android:name="com.google.android.glass.sample.timer.MenuActivity"
            android:label="@string/app_name"
            android:theme="@style/MenuTheme"
            android:enabled="true" >
        </activity>

        <activity
            android:name="com.google.android.glass.sample.timer.SetTimerActivity"
            android:label="@string/app_name"
            android:enabled="true" >
        </activity>

        <activity
            android:name="com.google.android.glass.sample.timer.SelectValueActivity"
            android:label="@string/app_name"
            android:enabled="true" >
        </activity>

        <service
            android:name="com.google.android.glass.sample.timer.TimerService"
            android:icon="@drawable/ic_timer"
            android:label="@string/app_name"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />
        </service>

    </application>

</manifest>


Activity が三つにServiceが一つ宣言されています。

こんなに小さなアプリでActivityが三つもあるのは何故か?

Glassでは基本的にActivityはコンテンツを描画する目的では無くメニューを表示する目的で使われます。従って、メニュー(設定項目や選択項目)が増えるとActivityがどんどん増えていく傾向があります。

Service内のmeta-dataは音声認識によるアプリ起動をサポートします。

次はソースコードを見て行きます。



  • MenuActivity.java

  • SelectValueActivity.java

  • SelectValueScrollAdapter.java

  • SetTimerActivity.java

  • SetTimerScrollAdapter.java

  • Timer.java

  • TimerDrawer.java

  • TimerService.java

  • TimerView.java

この中で最低限必要なクラスは以下です。



  • MenuActivity.java

  • TimerDrawer.java

  • TimerService.java

一つのGlassアプリには必ず一つのサービスが必要です。

サービスである為、アプリを終了する為のメニューが必要となるでしょう。必然的にメニューを表示するActivityも一つは必要となります。

さっき、Activityはメニューを表示する為に使うと説明しました。では、肝心のコンテンツはどのように描画するか?

GlassではCardというAndroidには無い仕組みが有ります。

Cardとは


Androidでは一つのActivityで一画面を表現しますが、Glassでは一つのCardで一つの画面を表現することができます。

CardにはStatic CardLive Cardの二種類があり、画面の更新頻度に応じて使い分けるとDocには書かれています。

TimerサンプルはLive Cardを利用している為、今回はLive Cardを使うことにします。

Live Cardは以下のような仕組みになっています。

http://developers.google.com/glass/images/diagrams/live-card-service.png

Glassではアプリ一覧が並ぶUIの事をTimelineと呼びます。

Timeline からアプリのサービスが起動し、サービスでLive Cardを生成しコンテンツの描画を行います。

HelloWorldを作ってみた


Timerサンプルを元に作成したHelloWorldのプロジェクト一式はこちら




重要なのはTimerServiceのonStartCommand()で、それ以外はAndroidと全く同じです。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (mLiveCard == null) {
        //LiveCardを生成したい
        mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);

        //レンダリング用Drawerを追加したい
        mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mTimerDrawer);
        
        //Menu用Activityの生成と追加をしたい
        Intent menuIntent = new Intent(this, MenuActivity.class);
        menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));

        //LiveCardを表示したい
        mLiveCard.publish(PublishMode.REVEAL);
    } else {
        // TODO(alainv): Jump to the LiveCard when API is available.
    }

    return START_STICKY;
}


尚、Cardを使わずAndroidと同様にActivityのみでアプリを構築する方法もあります。

しかしこの場合、そのままではTimelineからアプリを起動することができない為、アプリを起動する為だけのGlassアプリを用意する必要があります。これに関してはまた別の機会に書きます。

Glassの開発難易度


残念ながら現時点ではGlass用のシミュレータはありません。実機が無いとアプリのテストができない為、早急なシミュレータ環境の提供を期待するばかりです。

コードを書く事だけを見れば、Cardの概念さえ理解すれば後はAndroidとほとんど同じである為、Androidアプリ開発経験者はスムーズに開発を行うことができるでしょう。

しかし、実際にGlassを身につけるとよくわかるのですが、この最低限のアプリケーションでも、起動すると本体が非常に熱くなり、継続した装着が困難になります。

Glassで実用的なアプリケーションを構築する為には高度な省エネのスキルが要求されることでしょう。

しかし、Glassはソースコードが公開されていません。その為、基本的に Java 層で省エネを実現する必要があります。

実験的なアプリケーションはAndroidの延長線上で作れるものの、現時点のGlassの性能で実用的なアプリケーションをFixする為には非常に高度な開発スキルが求められると考えます。

Java で省エネって、アメ車に低燃費を求めるようなもんですよね




2013年12月21日土曜日




今回は、あまり余所のブログでは取り上げられていない領域識別子(identifier)に注目してみた。

CLBeaconRegionオブジェクトの生成時に指定するidentifier(日本語で言うと、識別子)は、領域の識別子である。これはそのアプリケーション内で自由に決められるものである。

CLBeaconRegionオブジェクトの初期化処理(initWith...)には、次の種類がある。

  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID identifier:(NSString *)identifier;
  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major identifier:(NSString *)identifier;
  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major minor:(CLBeaconMinorValue)minor identifier:(NSString *)identifier;

したがって、識別子をつけられる対象は、次のような組み合わせだけである。

組み合わせ

  • proximityUUID
  • proximityUUID、Major
  • proximityUUID、Major、Minor


ここからわかること、および、実際に動かしてわかったことがある:

1. 同じUUIDを持つデバイスが複数あるときに、3階層のグルーピングが可能である

2. 異なる組み合わせには、同じ識別子を付けられない
(実際、同じ識別子で異なるUUIDのCLBeaconRegionオブジェクトを作ろうとすると、後から作ったオブジェクトで上書きされてしまう)

3. 同じ組み合わせに対して、異なる識別子が付けられる

2つ目はあまり意識されていないところだと思うが、重要である。例えば、いろんなメーカーから購入したiBeaconデバイスを寄せ集めて、ひとつの領域を監視したいとする。しかし、そのようなiBeaconデバイスの中には、UUIDが予め決められていて、購入者が変更できないものもあるかもしれない。そうなると、これらのデバイスすべてを、同じ領域を表すためには使えないことになる。(たいていのiBeaconは、購入後もアプリケーションからUUIDが変更できるようになっている。)

この識別子、使い方によっては非常におもしろいことができる。ひとつのiBeaconに近づいたとか離れたとかといった使い方は基本中の基本で、本質的な使い方は、文字通り、領域にはいったかどうかである。例えば、同じUUID、MajorをもつiBeaconが、下図のように輪っかになっている場合は、そのUUIDとMajorの組に対して付けた識別子は、その赤い輪っかの領域を表す領域識別子として使用することができる。

3つ目の性質に着目すれば、同じビーコンでも異なる領域として使用可能なので、次図のように同じビーコンの配置に対して、いくつもの異なる領域が考えられる。(ただし、この場合、異なるビーコンには同じ識別子が使えないので、識別子自体をURLのようなドメイン構造にする工夫が必要となる。図では、aグループ、bグループ、cグループとしている。どのビーコンも2つの領域に属している。)

    


これは、iBeaconを社会インフラとして考えた場合、非常に柔軟に扱えることを意味している。たとえば、ある区域にiBeaconを均等に配置しておき、適切な識別子を与えただけで、あるルートを表す領域が取得でき、iBeaconの電波を拾って道案内を行うなど、低コストなナビゲーションシステムが実現できる。

例えば、次の図のように大阪駅構内にiBeaconを配置しておく、御堂筋北口から中央きっぷ売り場への道順を表す領域(赤枠)や、御堂筋南口から高速バスターミナルまでの道順を表す領域(青枠)など、おなじiBeaconインフラに対して、ことなる領域を定義することが可能となる。




領域の識別子をうまく使うことが、柔軟で低コストなiBeaconサービスを提供するための必須条件であることは間違いないだろう。


[Tips] iBeaconの領域識別子とは?




今回は、あまり余所のブログでは取り上げられていない領域識別子(identifier)に注目してみた。

CLBeaconRegionオブジェクトの生成時に指定するidentifier(日本語で言うと、識別子)は、領域の識別子である。これはそのアプリケーション内で自由に決められるものである。

CLBeaconRegionオブジェクトの初期化処理(initWith...)には、次の種類がある。

  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID identifier:(NSString *)identifier;
  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major identifier:(NSString *)identifier;
  • - (id)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major minor:(CLBeaconMinorValue)minor identifier:(NSString *)identifier;

したがって、識別子をつけられる対象は、次のような組み合わせだけである。

組み合わせ

  • proximityUUID
  • proximityUUID、Major
  • proximityUUID、Major、Minor


ここからわかること、および、実際に動かしてわかったことがある:

1. 同じUUIDを持つデバイスが複数あるときに、3階層のグルーピングが可能である

2. 異なる組み合わせには、同じ識別子を付けられない
(実際、同じ識別子で異なるUUIDのCLBeaconRegionオブジェクトを作ろうとすると、後から作ったオブジェクトで上書きされてしまう)

3. 同じ組み合わせに対して、異なる識別子が付けられる

2つ目はあまり意識されていないところだと思うが、重要である。例えば、いろんなメーカーから購入したiBeaconデバイスを寄せ集めて、ひとつの領域を監視したいとする。しかし、そのようなiBeaconデバイスの中には、UUIDが予め決められていて、購入者が変更できないものもあるかもしれない。そうなると、これらのデバイスすべてを、同じ領域を表すためには使えないことになる。(たいていのiBeaconは、購入後もアプリケーションからUUIDが変更できるようになっている。)

この識別子、使い方によっては非常におもしろいことができる。ひとつのiBeaconに近づいたとか離れたとかといった使い方は基本中の基本で、本質的な使い方は、文字通り、領域にはいったかどうかである。例えば、同じUUID、MajorをもつiBeaconが、下図のように輪っかになっている場合は、そのUUIDとMajorの組に対して付けた識別子は、その赤い輪っかの領域を表す領域識別子として使用することができる。

3つ目の性質に着目すれば、同じビーコンでも異なる領域として使用可能なので、次図のように同じビーコンの配置に対して、いくつもの異なる領域が考えられる。(ただし、この場合、異なるビーコンには同じ識別子が使えないので、識別子自体をURLのようなドメイン構造にする工夫が必要となる。図では、aグループ、bグループ、cグループとしている。どのビーコンも2つの領域に属している。)

    


これは、iBeaconを社会インフラとして考えた場合、非常に柔軟に扱えることを意味している。たとえば、ある区域にiBeaconを均等に配置しておき、適切な識別子を与えただけで、あるルートを表す領域が取得でき、iBeaconの電波を拾って道案内を行うなど、低コストなナビゲーションシステムが実現できる。

例えば、次の図のように大阪駅構内にiBeaconを配置しておく、御堂筋北口から中央きっぷ売り場への道順を表す領域(赤枠)や、御堂筋南口から高速バスターミナルまでの道順を表す領域(青枠)など、おなじiBeaconインフラに対して、ことなる領域を定義することが可能となる。




領域の識別子をうまく使うことが、柔軟で低コストなiBeaconサービスを提供するための必須条件であることは間違いないだろう。


2013年12月19日木曜日


ビーコンって何を考えてるんでしょうね?聞いてみたいと思いませんか?

と、唐突に書き始めてしまいました。開発のやりすぎで頭がおかしくなったのでしょうか? いえ、そうではなくて、今回は、ビーコンの近さに応じて、再生する音の大きさを変えてみようというお話です。でも、それはまるで、ビーコンが「近づいたよ〜」「遠のいたよ〜」と言っているように聞こえるので、結構、たのしいのです。(実際には、電波が強くなったよ〜、ですが。。。)

では、さっそく作って行きます。

1.ボタンを押したら、曲を再生する、というところまでを作ります。xcodeのプロジェクト(BeaconVoiceという名前にしました)を作成し、AVFoundation.frameworkを追加します。また、"sounds"というフォルダを作成し、そこに用意したMP3ファイルをおきます(図参照)。


画面はこんな感じ(図参照)。

しょぼいですね〜。音量と電波受信強度のラベルだけはつけときました。

ソースコードは、こんな感じです。(STARTボタンを押すと、曲が再生されて、もう一度押すと、停止する、という動きにしてます。)

ViewController.m


はい、では、次行きましょう。

2.CoreLocation.frameworkをセットして、ビーコンを受信できるようにします。この辺りは、このブログで何回か紹介してますので、コードだけ載っけます。

ViewController.hのプロパティ

ViewController.mのViewDidLoadの中

ViewController.mの中のLocationManagerのデリゲート処理

はい、できました!

では、実行の様子をお聴きください...。


ああ、残念です。音声がお伝えできない。

音量は、0.0〜1.0までの値です。RSSIの値は、-90〜-58にしています。つまり、この画像では、最大値になっています。iPhoneもビーコンもスクリーンショットを撮った開発環境のPCに接続しているので無理ないですね。では、ちょっとビーコンを遠くへ離してみます。

か、かすかに音が聞こえます。そして、ときどき、ゴハッって感じで音が大きくなります。まるで溺れかけの人のように。おおお、いい感じでビーコンの声が聞こえてますね。

まとめ

もともとビーコンの電波がどれくらい不安定なのか知りたく思い、音で体感できるようにしたかっただけなのですが、なかなかいい感じで確認できることがわかりました。例えるなら、トンネルに入ったときのラジオの音でしょうか?でも、ビーコンに近いときは、安定して聴けます。

応用として、ある範囲では、クラシック、ある範囲では、ジャズなど、特定の範囲でだけ特定の音楽が聴けるとかのサービスができそうですね。

(おわり)

ビーコンの声を聞いてみよう!


ビーコンって何を考えてるんでしょうね?聞いてみたいと思いませんか?

と、唐突に書き始めてしまいました。開発のやりすぎで頭がおかしくなったのでしょうか? いえ、そうではなくて、今回は、ビーコンの近さに応じて、再生する音の大きさを変えてみようというお話です。でも、それはまるで、ビーコンが「近づいたよ〜」「遠のいたよ〜」と言っているように聞こえるので、結構、たのしいのです。(実際には、電波が強くなったよ〜、ですが。。。)

では、さっそく作って行きます。

1.ボタンを押したら、曲を再生する、というところまでを作ります。xcodeのプロジェクト(BeaconVoiceという名前にしました)を作成し、AVFoundation.frameworkを追加します。また、"sounds"というフォルダを作成し、そこに用意したMP3ファイルをおきます(図参照)。


画面はこんな感じ(図参照)。

しょぼいですね〜。音量と電波受信強度のラベルだけはつけときました。

ソースコードは、こんな感じです。(STARTボタンを押すと、曲が再生されて、もう一度押すと、停止する、という動きにしてます。)

ViewController.m


はい、では、次行きましょう。

2.CoreLocation.frameworkをセットして、ビーコンを受信できるようにします。この辺りは、このブログで何回か紹介してますので、コードだけ載っけます。

ViewController.hのプロパティ

ViewController.mのViewDidLoadの中

ViewController.mの中のLocationManagerのデリゲート処理

はい、できました!

では、実行の様子をお聴きください...。


ああ、残念です。音声がお伝えできない。

音量は、0.0〜1.0までの値です。RSSIの値は、-90〜-58にしています。つまり、この画像では、最大値になっています。iPhoneもビーコンもスクリーンショットを撮った開発環境のPCに接続しているので無理ないですね。では、ちょっとビーコンを遠くへ離してみます。

か、かすかに音が聞こえます。そして、ときどき、ゴハッって感じで音が大きくなります。まるで溺れかけの人のように。おおお、いい感じでビーコンの声が聞こえてますね。

まとめ

もともとビーコンの電波がどれくらい不安定なのか知りたく思い、音で体感できるようにしたかっただけなのですが、なかなかいい感じで確認できることがわかりました。例えるなら、トンネルに入ったときのラジオの音でしょうか?でも、ビーコンに近いときは、安定して聴けます。

応用として、ある範囲では、クラシック、ある範囲では、ジャズなど、特定の範囲でだけ特定の音楽が聴けるとかのサービスができそうですね。

(おわり)

Related Posts Plugin for WordPress, Blogger...